00001
00002
00003 #ifndef _AOFHEAP_H_
00004 #define _AOFHEAP_H_
00005
00006 #include <new>
00007 using namespace std;
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 template <class SuperHeap, int FreeThreshold>
00030 class AOFFHeap : public SuperHeap {
00031 public:
00032
00033 AOFFHeap (void)
00034 {
00035 freeList.setSize (0);
00036 freeList.setNext (&freeList);
00037 freeList.setPrev (&freeList);
00038 }
00039
00040 ~AOFFHeap (void) {
00041 return;
00042
00043 freedObject * ptr = freeList.getNext();
00044 while (ptr != &freeList) {
00045 freedObject * prev = ptr;
00046 ptr = ptr->getNext();
00047 SuperHeap::free (prev);
00048 }
00049 }
00050
00051 void * malloc (size_t sz) {
00052
00053 assert (isValid());
00054 assert (sz >= sizeof(freedObject) - sizeof(allocatedObject));
00055
00056 freedObject * ptr = freeList.getNext();
00057 while ((ptr != &freeList) && (ptr->getSize() < sz + sizeof(freedObject))) {
00058 ptr = ptr->getNext();
00059 }
00060
00061
00062 if (ptr == &freeList) {
00063
00064
00065
00066 void * buf = SuperHeap::malloc (sz + sizeof(allocatedObject));
00067 if (buf == NULL) {
00068 assert (isValid());
00069 return NULL;
00070 }
00071 freedObject * newptr
00072 = new (buf) freedObject (sz, NULL, NULL);
00073 assert (size(newptr->getStart()) == sz);
00074 assert (isValid());
00075 return (void *) newptr->getStart();
00076 } else {
00077 assert (ptr->getSize() >= sz);
00078
00079 freedObject * prev = ptr->getPrev();
00080 freedObject * next = ptr->getNext();
00081 assert (prev->isValid());
00082 assert (next->isValid());
00083
00084
00085 if (ptr->getSize() - sz >= sizeof(freedObject)) {
00086
00087
00088 size_t oldSize = ptr->getSize();
00089 ptr->setSize (sz);
00090 freedObject * splicedObj = new (ptr->getSuccessor())
00091 freedObject (oldSize - sz - sizeof(freedObject),
00092 prev,
00093 next);
00094 prev->setNext (splicedObj);
00095 next->setPrev (splicedObj);
00096 assert (splicedObj->isValid());
00097 assert (isValid());
00098 assert (size(ptr->getStart()) == sz);
00099 return (void *) ptr->getStart();
00100 } else {
00101 assert (0);
00102 abort();
00103
00104
00105 prev->setNext (next);
00106 next->setPrev (prev);
00107 assert (isValid());
00108 assert (size(ptr->getStart()) == sz);
00109 return (void *) ptr->getStart();
00110 }
00111 }
00112 }
00113
00114 void free (void * p) {
00115 assert (isValid());
00116
00117 freedObject * thisObject = (freedObject *) ((char *) p - sizeof(allocatedObject));
00118 assert (thisObject->getStart() == p);
00119 freedObject * prev = &freeList;
00120 freedObject * next = freeList.getNext();
00121 while ((next != &freeList) && ((char *) thisObject > (char *) next)) {
00122 prev = next;
00123 next = next->getNext();
00124 }
00125
00126
00127 if (thisObject == next) {
00128
00129
00130 return;
00131 }
00132
00133 prev->setNext (thisObject);
00134 next->setPrev (thisObject);
00135 thisObject = new (thisObject) freedObject (thisObject->getSize(), prev, next);
00136
00137 if (prev->getSuccessor() == thisObject) {
00138 assert (prev != &freeList);
00139 coalesce (prev, thisObject);
00140 thisObject = prev;
00141 assert (thisObject->isValid());
00142 assert (thisObject->getSize() > 0);
00143
00144 }
00145 if (thisObject->getSuccessor() == next) {
00146 coalesce (thisObject, next);
00147 assert (thisObject->isValid());
00148
00149 }
00150
00151 if (thisObject->getSize() >= FreeThreshold) {
00152
00153 freedObject * prev = thisObject->getPrev();
00154 freedObject * next = thisObject->getNext();
00155 prev->setNext (next);
00156 next->setPrev (prev);
00157 assert (thisObject->isValid());
00158 SuperHeap::free (thisObject);
00159 }
00160 assert (isValid());
00161 }
00162
00163
00164 inline static size_t size (void * p)
00165 {
00166 allocatedObject * thisObject = (allocatedObject *) p - 1;
00167 assert (thisObject->isValid());
00168 return thisObject->getSize();
00169 }
00170
00171
00172 private:
00173
00174 int isValid (void) {
00175
00176 freedObject * ptr = freeList.getNext();
00177 while (ptr != &freeList) {
00178 freedObject * prev = ptr;
00179 assert (prev->getNext()->getPrev() == prev);
00180 assert (prev->isValid());
00181 ptr = ptr->getNext();
00182 }
00183 return 1;
00184 }
00185
00186 class freedObject;
00187
00188 inline void coalesce (freedObject * curr, freedObject * succ) {
00189
00190 assert (curr->getSuccessor() == succ);
00191 assert (succ->getPrev() == curr);
00192 assert (curr->getNext() == succ);
00193 curr->setNext (succ->getNext());
00194 succ->getNext()->setPrev(curr);
00195 curr->setSize (curr->getSize() + succ->getSize() + sizeof(allocatedObject));
00196 assert (curr->isValid());
00197 }
00198 inline static size_t align (int sz) {
00199 return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1);
00200 }
00201
00202 class allocatedObject {
00203 public:
00204 allocatedObject (void)
00205 {
00206 size = 0;
00207 #ifndef NDEBUG
00208 magic = 0xfacefade;
00209 #endif
00210 }
00211 int isValid (void) const {
00212 return (size >= 0) && (magic == 0xfacefade);
00213 }
00214 void setSize (size_t sz) { size = sz; assert (isValid()); }
00215 int getSize (void) const { assert (isValid()); return size; }
00216
00217
00218 allocatedObject * getSuccessor (void) const {
00219 assert (isValid());
00220 return (allocatedObject *) ((char *) (this + 1) + size);
00221 }
00222
00223
00224 char * getStart (void) const {
00225 assert (isValid());
00226 return ((char *) (this + 1));
00227 }
00228 private:
00229 int size;
00230 int magic;
00231 };
00232
00233 class freedObject : public allocatedObject {
00234 public:
00235 freedObject (void)
00236 : prev ((freedObject *) 0xdeadbeef),
00237 next ((freedObject *) 0xdeadbeef)
00238 {}
00239 freedObject (size_t sz,
00240 freedObject * p,
00241 freedObject * n)
00242 : prev (p),
00243 next (n)
00244 {
00245 allocatedObject::setSize (sz);
00246 }
00247 int isValid (void) const {
00248 return (allocatedObject::isValid());
00249 }
00250 freedObject * getPrev (void) const { assert (isValid()); return prev; }
00251 freedObject * getNext (void) const { assert (isValid()); return next; }
00252 void setPrev (freedObject * p) { assert (isValid()); prev = p; }
00253 void setNext (freedObject * p) { assert (isValid()); next = p; }
00254 private:
00255 freedObject * prev;
00256 freedObject * next;
00257 };
00258
00259
00260 freedObject freeList;
00261 double _dummy;
00262 };
00263
00264 #endif