00001
00002
00003 #ifndef _COALESCEHEAP_H_
00004 #define _COALESCEHEAP_H_
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <assert.h>
00031
00032 #include "heaplayers.h"
00033
00041 namespace HL {
00042
00043 template <class super>
00044 class CoalesceHeap : public super {
00045 public:
00046
00047 inline void * malloc (const size_t sz)
00048 {
00049 void * ptr = super::malloc (sz);
00050 if (ptr != NULL) {
00051 super::markInUse (ptr);
00052 void * splitPiece = split (ptr, sz);
00053 if (splitPiece != NULL) {
00054 super::markFree (splitPiece);
00055 super::free (splitPiece);
00056 }
00057 }
00058 return ptr;
00059 }
00060
00061
00062 inline void free (void * ptr)
00063 {
00064
00065 if ((super::getNext(super::getPrev(ptr)) != ptr) || (super::getPrev(super::getNext(ptr)) != ptr)) {
00066
00067 super::free (ptr);
00068 return;
00069 }
00070 assert (super::getPrev(super::getNext(ptr)) == ptr);
00071
00072 void * prev = super::getPrev(ptr);
00073 void * next = super::getNext (ptr);
00074 assert (prev != ptr);
00075
00076 if (super::isPrevFree(ptr)) {
00077 assert (super::isFree(prev));
00078 super::remove (prev);
00079 coalesce (prev, ptr);
00080 ptr = prev;
00081 }
00082 if (super::isFree(next)) {
00083 super::remove (next);
00084 coalesce (ptr, next);
00085 }
00086
00087 super::markFree (ptr);
00088
00089
00090 super::free (ptr);
00091 }
00092
00093 private:
00094
00095
00096
00097 inline static void coalesce (void * first, const void * second) {
00098
00099 assert (super::getNext(first) == second);
00100 assert (super::getPrev(second) == first);
00101
00102 size_t newSize = ((size_t) second - (size_t) first) + super::getSize(second);
00103 super::setSize (first, newSize);
00104 setPrevSize (super::getNext(first), newSize);
00105 }
00106
00107
00108 inline static void * split (void * obj, const size_t requestedSize) {
00109 assert (super::getSize(obj) >= requestedSize);
00110
00111 const size_t actualSize = super::getSize(obj);
00112 if (actualSize - requestedSize >= sizeof(typename super::Header) + sizeof(double)) {
00113
00114 super::setSize(obj, requestedSize);
00115 void * splitPiece = (char *) obj + requestedSize + sizeof(typename super::Header);
00116 super::makeObject ((void *) super::getHeader(splitPiece),
00117 requestedSize,
00118 actualSize - requestedSize - sizeof(typename super::Header));
00119 assert (!super::isFree(splitPiece));
00120
00121
00122 (super::getHeader(splitPiece))->markPrevInUse();
00123 assert (super::getSize(splitPiece) >= sizeof(double));
00124 assert (super::getSize(obj) >= requestedSize);
00125 return splitPiece;
00126 } else {
00127 return NULL;
00128 }
00129 }
00130
00131 };
00132
00133 };
00134
00135
00136 #endif