home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c100 / 2.ddi / GCOBJECT.ZIP / GCOBJECT.CPP next >
Encoding:
C/C++ Source or Header  |  1990-07-09  |  4.0 KB  |  120 lines

  1. /**************************************************************************
  2. These C++ classes are copyright 1989, 1990 by William Herrera.
  3. All those who put this code or its derivatives in a commercial product MUST
  4. mention this copyright in their documentation for users of the products in
  5. which this code or its derivative classes are used.  Otherwise, this code
  6. may be freely distributed and used for any purpose.
  7. William Herrera
  8. contacts:
  9. GENIE
  10. FidoNet c_plusplus
  11. **************************************************************************/
  12. // file gcobject.cpp class definition for functions in gcobject class.
  13.  
  14. #include "gcobject.hpp"
  15.  
  16. char heap_alloc_err[] = "Error:  Out of heap space";
  17. char gcobject_alloc_err[] = "Error:  Out of gcobject space";
  18. char cr[] = "\n";
  19.  
  20. void gcobject::Initialize(unsigned int buf_size, int gci)
  21. {
  22.     buffer_size = buf_size;
  23.     buffer_start = ::new char[buffer_size];
  24.     if(buffer_start == NULL)
  25.         FatalError(heap_alloc_err);
  26.     allocated_size = 0;
  27.     delete_count = 0;
  28.     garbage_collection_interval = gci;
  29. }
  30.  
  31. int gcobject::CollectGarbage()
  32. {
  33. #ifdef DEBUG
  34.     cerr << "\nCollecting Garbage ...\n";
  35. #endif
  36.     int num_collected = 0;        // number of data_records collected out.
  37.     unsigned int garbage_bottom = 0;
  38.     data_record * dptr;
  39.     while(garbage_bottom < allocated_size)
  40.     {
  41.         dptr = (data_record *) &buffer_start[garbage_bottom];
  42.         if(dptr->ref_count == 0)    // dptr points to garbage
  43.             break;                    // so exit
  44.         garbage_bottom += dptr->alloc_length; // skip past area in use
  45.     }    // now we have found an area of garbage (ref_count == 0).
  46.     unsigned int garbage_top = garbage_bottom;
  47.     while(garbage_top < allocated_size)
  48.     {
  49.         dptr = (data_record *) &buffer_start[garbage_top];
  50.         if(dptr->ref_count != 0)    // dptr points to non-garbage
  51.             break;                    // so exit
  52.         garbage_top += dptr->alloc_length;    // skip past garbage record
  53.         ++num_collected;    // we've got one to collect.
  54.     }
  55.     if(garbage_bottom < allocated_size && num_collected > 0)
  56.                             // there is stuff to collect!
  57.     {
  58.         unsigned int bytes_above_garbage = allocated_size - garbage_top;
  59.         if(bytes_above_garbage > 0)
  60.             memmove(&buffer_start[garbage_bottom], 
  61.                 &buffer_start[garbage_top],    bytes_above_garbage);
  62.                             // move stuff to cover garbage.
  63.         allocated_size -= garbage_top - garbage_bottom; 
  64.                     // reset amount of buffer currently used.
  65.         // Now update the allocated pointers to the buffer records.
  66.         // Each record in the buffer keeps track of what pointer is pointing
  67.         // to it and can change its value when we reshuffle the buffer.
  68.         unsigned int i = 0;
  69.         while(i < allocated_size)
  70.         {
  71.             dptr = (data_record *) &buffer_start[i];
  72.             data_record ** owner = dptr->owner_record;
  73.             *owner = dptr;
  74.             i += dptr->alloc_length;
  75.         }
  76.     }
  77.     delete_count = 0;        // reset the counter, since we've done garbage.
  78.     return num_collected;    // this is zero if there was none to collect.
  79. }
  80.  
  81. data_record * gcobject::Allocate(size_t sz, data_record ** owner)
  82. {
  83.     // this function allocates memory to pointer "owner" but keeps
  84.     // track of owner's address so it can update owner if the
  85.     // allocation changes position.
  86.     size_t len = sizeof(data_record) - 1 + sz;
  87.         // this is the size of the variable length records in the buffer.
  88.     if(len & 1) // odd # of bytes
  89.         ++len;  // so make even for alignment.
  90.     while(allocated_size + len > buffer_size)    // oops, out of room
  91.     {
  92.         if(CollectGarbage() == 0)    // try to get some space!
  93.             return NULL;            // if can't, return NULL as failure flag.
  94.     }
  95.     data_record * dptr = (data_record *) &buffer_start[allocated_size];
  96.     allocated_size += len;
  97.     dptr->alloc_length = len;
  98.     dptr->ref_count = 1;    // base reference count is always 1.
  99.     dptr->owner_record = owner;
  100.     return dptr;
  101. }
  102.  
  103. void gcobject::IncDeleteCount()
  104. {
  105.     ++delete_count;
  106.     if(delete_count > garbage_collection_interval)
  107.         CollectGarbage();
  108. }
  109.  
  110. #ifdef DEBUG
  111. void gcobject::DumpBuffer()
  112. {
  113.     for(unsigned int i = 0; i < buffer_size; ++i)
  114.         cerr.put(buffer_start[i]);
  115.     cerr.put('\n');
  116. }
  117. #endif
  118.  
  119. // end of file gcobject.cpp
  120.