home *** CD-ROM | disk | FTP | other *** search
/ Prima Shareware 3 / DuCom_Prima-Shareware-3_cd1.bin / PROGRAMO / C / GCSTRI / GCOBJECT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-26  |  4.4 KB  |  154 lines

  1. /**************************************************************************
  2. These C++ classes are copyright 1989, 1990, 1991 by William Herrera.
  3. I hereby release this source code for free distrubution and use.
  4. If you modify it and distribute it, please indicate any changes you
  5. make as your own and the code as copyrighted above.
  6. **************************************************************************/
  7.  
  8. // file gcobject.cpp class definition for functions in gcobject class.
  9.  
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #include <limits.h>
  14. #include <fstream.h>
  15. #include <alloc.h>
  16.  
  17.  
  18. #include "gcobject.hpp"
  19. #include "error.hpp"
  20.  
  21. const char handle_alloc_err[] = "Error:  Out of handle space";
  22. const char gcobject_alloc_err[] = "Error:  Out of gcobject space";
  23.  
  24. gcobject::gcobject(unsigned int buf_size, int gci)
  25.     : buffer_size(buf_size), garbage_collection_interval(gci),
  26.     allocated_size(0), delete_count(0), lockcount(0)
  27. {
  28.     buffer_start = ::new char[buffer_size];
  29.     if(buffer_start == NULL)
  30.         Error(handle_alloc_err);
  31. }
  32.  
  33. gcobject::~gcobject()
  34. {
  35.     if(buffer_start != NULL)
  36.         delete buffer_start;
  37. }
  38.  
  39. void gcobject::CompactBuffer()
  40. {
  41.     while(CollectGarbage() != 0)    // collect until all compacted.
  42.         ;
  43. }
  44.  
  45. void gcobject::Lock()
  46. {
  47.     ++lockcount;
  48. }
  49.  
  50. void gcobject::Unlock()
  51. {
  52.     --lockcount;
  53. }
  54.  
  55. int gcobject::CollectGarbage()
  56. {
  57.     if(lockcount != 0)    // the buffer is locked.
  58.         return 0;
  59. #ifdef DEBUG
  60.     cerr << "\nCollecting Garbage ...\n";
  61. #endif
  62.     int num_collected = 0;        // number of data_records collected out.
  63.     unsigned int garbage_bottom = 0;
  64.     data_record * dptr;
  65.     while(garbage_bottom < allocated_size)
  66.     {
  67.         dptr = (data_record *) &buffer_start[garbage_bottom];
  68.         if(dptr->ref_count == 0)    // dptr points to garbage
  69.             break;                    // so exit
  70.         garbage_bottom += dptr->alloc_length; // skip past area in use
  71.     }    // now we have found an area of garbage (ref_count == 0).
  72.     unsigned int garbage_top = garbage_bottom;
  73.     while(garbage_top < allocated_size)
  74.     {
  75.         dptr = (data_record *) &buffer_start[garbage_top];
  76.         if(dptr->ref_count != 0)    // dptr points to non-garbage
  77.             break;                    // so exit
  78.         garbage_top += dptr->alloc_length;    // skip past garbage record
  79.         ++num_collected;    // we've got one to collect.
  80.     }
  81.     if(garbage_bottom < allocated_size && num_collected > 0)
  82.                             // there is stuff to collect!
  83.     {
  84.         unsigned int bytes_above_garbage = allocated_size - garbage_top;
  85.         if(bytes_above_garbage > 0)
  86.             memmove(&buffer_start[garbage_bottom],
  87.                 &buffer_start[garbage_top],    bytes_above_garbage);
  88.                             // move stuff to cover garbage.
  89.         allocated_size -= garbage_top - garbage_bottom;
  90.                     // reset amount of buffer currently used.
  91.         // Now update the allocated pointers to the buffer records.
  92.         // Each record in the buffer keeps track of what pointer is pointing
  93.         // to it and can change its value when we reshuffle the buffer.
  94.         unsigned int i = 0;
  95.         while(i < allocated_size)
  96.         {
  97.             dptr = (data_record *) &buffer_start[i];
  98.             data_record ** owner = dptr->owner_record;
  99.             if(dptr->ref_count > 0)
  100.                 *owner = dptr;
  101.             i += dptr->alloc_length;
  102.         }
  103.     }
  104.     delete_count = 0;        // reset the counter, since we've done garbage.
  105.     return num_collected;    // this is zero if there was none to collect.
  106. }
  107.  
  108. void gcobject::Allocate(size_t sz, data_record ** owner)
  109. {
  110.     // this function allocates memory to pointer "owner" but keeps
  111.     // track of owner's address so it can update owner if the
  112.     // allocation changes position.
  113.     size_t len = sizeof(data_record) - 1 + sz;
  114.         // this is the size of the variable length records in the buffer.
  115.     if(len & 1) // odd # of bytes
  116.         ++len;  // so make even for alignment.
  117.     while(allocated_size + len > buffer_size)    // oops, out of room
  118.     {
  119.         if(CollectGarbage() == 0)    // try to get some space!
  120.         {
  121.             *owner = NULL;            // if can't, assign NULL as failure flag.
  122.             return;
  123.         }
  124.     }
  125.     data_record * dptr = (data_record *) &buffer_start[allocated_size];
  126.     allocated_size += len;
  127.     dptr->alloc_length = len;
  128.     dptr->ref_count = 1;    // base reference count is always 1.
  129.     dptr->owner_record = owner;
  130.     *owner = dptr;
  131.     return;
  132. }
  133.  
  134. void gcobject::IncDeleteCount()
  135. {
  136.     ++delete_count;
  137.     if(delete_count > garbage_collection_interval)
  138.         CollectGarbage();
  139. }
  140.  
  141.  
  142. #ifdef DEBUG
  143. void gcobject::DumpBuffer()
  144. {
  145.     for(unsigned int i = 0; i < buffer_size; ++i)
  146.         cerr.put(buffer_start[i]);
  147.     cerr.put('\n');
  148. }
  149. #endif
  150.  
  151.  
  152.  
  153. // end of file gcobject.cpp
  154.