Main Page | Namespace List | Class Hierarchy | Compound List | File List | Compound Members | File Members | Related Pages

Memory.hpp

Go to the documentation of this file.
00001 
00027 //
00028 //  Memory handling for small and other structures
00029 //  For small structures the memory handling is optimized
00030 //
00031 //  In the debug mode 
00032 //    (1) can keep track of the amount of local and global memory allocated
00033 //    (2) provides functions to check validity of a small memory piece
00034 //    (3) halts on the deallocated of memory that was not allocated or
00035 //        is deallocated
00036 //    (4) can print all allocated but not deallocated structures (memory leak)
00037 //
00038 //  20/11/1999 Manchester, made from memory.h in kk
00039 //  14/02/2000 Manchester, reimplemented completely
00040 //  27/02/2002 Manchester, name () changed to classID ()
00041 //
00042 
00043 
00044 //
00045 //  Allocated objects of the class must be of the same length
00046 //  and not allocated before the memory initialiser is called
00047 // 
00048 
00049 #ifndef __memory__
00050 #  define __memory__
00051 
00052 
00053 #include <cstdlib>
00054 
00055 #include "assert.hpp"
00056 
00057 
00058 // it is essential that the class IDs are enumerated in order, each one is 
00059 // unique, and CID_TOTAL_NUMBER gives their number.
00060 //
00061 enum ClassID {
00062   CID_VTERM,
00063   CID_CTERM,
00064   CID_NTERM,
00065   CID_ATOM,
00066   CID_QFORMULA,
00067   CID_VARLIST,
00068   CID_INTLIST,
00069   CID_VARLIST_LIST,
00070   CID_ASSOC_PAIR_LIST,
00071   CID_SYMBOL,
00072   CID_FSYM_LIST,
00073   CID_PSYM_LIST,
00074   CID_TERM_LIST,
00075   CID_ATOM_LIST,
00076   CID_LITERAL,
00077   CID_LITERAL_LIST,
00078   CID_CLAUSE,
00079   CID_CLAUSE_LIST,
00080   CID_FORMULA_LIST,
00081   CID_ENTRY,
00082   CID_ENTRY_LIST,
00083   CID_UNIT,
00084   CID_UNIT_LIST,
00085   CID_UNIT_LINK,
00086   CID_NAME_TABLE,
00087   CID_BINDING,
00088   CID_BINDING_LIST,
00089   CID_REN_BINDING,
00090   CID_REN_BINDING_LIST,
00091   CID_OPTION_LIST,
00092   CID_ULONG_LIST,
00093   CID_KERNEL_CLAUSE_LIST,
00094   CID_FORALL_OR_MINISCOPE,
00095   CID_DUMMY_QUANTIFIER_REMOVAL,
00096   CID_FLATTEN,
00097   CID_INFERENCE_TYPE1
00098 }; // enum ClassIDs
00099 
00100 
00101 // could not make it in-class since it must be global for all memories
00102 extern const char* id2name (ClassID);
00103 
00104 
00105 template <ClassID CID>
00106 class Memory 
00107 {
00108  public:
00109   void* operator new (size_t size)
00110   {
00111     _allocs ++;
00112 
00113     if (_freeList) {
00114       Memory* _result = _freeList;
00115       _freeList = _freeList->_next;
00116       return _result;
00117     }
00118 
00119     if (void* res = ::operator new (size)) {
00120       return res;
00121     }
00122     NO_MEMORY;
00123   } // Memory::operator new
00124 
00125 
00126   void operator delete (void* obj)
00127   {
00128     _deallocs ++;
00129 
00130     Memory* m = reinterpret_cast <Memory*>(obj);
00131     m->_next = _freeList;
00132     _freeList = m;
00133   }
00134 
00135   bool isValid () const
00136   {
00137     return (_id == CID) && (_allocationTag == ALLOCATED);
00138   }
00139 
00140   Memory () 
00141     :
00142     // mark the object as allocated
00143     _allocationTag (ALLOCATED),
00144     _id (CID)
00145   {
00146     if ( _allocated ) { // there was an allocated oject
00147       _next = _allocated;
00148       _previous = _allocated->_previous;
00149       if ( _allocated->_previous != 0 ) {
00150         _allocated->_previous->_next = this;
00151       }
00152       _allocated->_previous  = this;
00153     }
00154     else { // there was no allocated object
00155       _next = 0;
00156       _previous = 0;
00157       _allocated = this;
00158     }
00159   }
00160 
00161   ~Memory ()
00162   {
00163     if ( _allocationTag == DEALLOCATED ) {
00164       cerr << "Attempt to delete an already deleted object " << (void*)this << " of class " <<
00165               id2name (CID) << "\n";
00166       exit (EXIT_FAILURE);
00167     }
00168     if ( ! isValid () ) {
00169       cerr << "Trying to delete an object of class " <<
00170               id2name (CID) << ", but accessing an invalid memory piece\n";
00171       exit (EXIT_FAILURE);
00172     }
00173 
00174     // mark the object as de-allocated
00175     _allocationTag = DEALLOCATED;
00176 
00177     if (_next) {
00178       _next->_previous = _previous;
00179     }
00180     if (_previous) {
00181       _previous->_next = _next;
00182     }
00183     if ( _allocated == this ) {
00184       _allocated = _next ? _next : _previous;
00185     }
00186     // free-list will be changed by operator delete
00187   }
00188 
00189   class LeakChecker {
00190    public:
00191     LeakChecker () {}
00192     ~LeakChecker ()
00193     {
00194       if (Memory::_allocated) {
00195         int leaks = 0;
00196         for (Memory* n = Memory::_allocated; n; n = n->_next) {
00197           leaks ++;
00198         }
00199         for (Memory* p = Memory::_allocated->_previous; p; p = p->_previous) {
00200           leaks ++;
00201         }
00202         cout << "Class " << id2name (CID) << "\n"
00203                 "  allocations: " << Memory::_allocs << "\n"
00204                 "  deallocations: " << Memory::_deallocs << "\n";
00205         cout << "Class " << id2name (CID) << " has memory leaks (" <<
00206                 leaks << " pieces)\n";
00207       }
00208     }
00209   };
00210 
00211   friend class LeakChecker;
00212 
00213  private:
00214   enum AllocationTag {
00215     ALLOCATED = 1234732,    // any two garbage values
00216     DEALLOCATED = 2374321
00217   };
00218 
00219   // structure
00220   Memory* _next;      // next in the free list, or next among allocated
00221   Memory* _previous;  // previous among allocated
00222   AllocationTag _allocationTag;
00223   const enum ClassID _id;      // must always be classID
00224 
00225   static Memory* _freeList;
00226   static Memory* _allocated;    // any allocated object, initially 0
00227   static int _allocs;
00228   static int _deallocs;
00229 }; // class Memory
00230 
00231 
00232 #endif

Generated on Sat Jun 28 15:08:57 2003 for Vampire by doxygen 1.3.2