00001
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #ifndef __memory__
00050 # define __memory__
00051
00052
00053 #include <cstdlib>
00054
00055 #include "assert.hpp"
00056
00057
00058
00059
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 };
00099
00100
00101
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 }
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
00143 _allocationTag (ALLOCATED),
00144 _id (CID)
00145 {
00146 if ( _allocated ) {
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 {
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
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
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,
00216 DEALLOCATED = 2374321
00217 };
00218
00219
00220 Memory* _next;
00221 Memory* _previous;
00222 AllocationTag _allocationTag;
00223 const enum ClassID _id;
00224
00225 static Memory* _freeList;
00226 static Memory* _allocated;
00227 static int _allocs;
00228 static int _deallocs;
00229 };
00230
00231
00232 #endif