Eneboo - Documentación para desarrolladores
|
00001 /* -*- C++ -*- */ 00002 00003 #ifndef _COALESCEHEAP_H_ 00004 #define _COALESCEHEAP_H_ 00005 00006 /* 00007 00008 Heap Layers: An Extensible Memory Allocation Infrastructure 00009 00010 Copyright (C) 2000-2003 by Emery Berger 00011 http://www.cs.umass.edu/~emery 00012 emery@cs.umass.edu 00013 00014 This program is free software; you can redistribute it and/or modify 00015 it under the terms of the GNU General Public License as published by 00016 the Free Software Foundation; either version 2 of the License, or 00017 (at your option) any later version. 00018 00019 This program is distributed in the hope that it will be useful, 00020 but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License 00025 along with this program; if not, write to the Free Software 00026 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 // Try to coalesce this object with its predecessor & successor. 00065 if ((super::getNext(super::getPrev(ptr)) != ptr) || (super::getPrev(super::getNext(ptr)) != ptr)) { 00066 // We're done with this object. 00067 super::free (ptr); 00068 return; 00069 } 00070 assert (super::getPrev(super::getNext(ptr)) == ptr); 00071 // Try to coalesce with the previous object.. 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 // We're done with this object. 00090 super::free (ptr); 00091 } 00092 00093 private: 00094 00095 00096 // Combine the first object with the second. 00097 inline static void coalesce (void * first, const void * second) { 00098 // A few sanity checks first. 00099 assert (super::getNext(first) == second); 00100 assert (super::getPrev(second) == first); 00101 // Now coalesce. 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 // Split an object if it is big enough. 00108 inline static void * split (void * obj, const size_t requestedSize) { 00109 assert (super::getSize(obj) >= requestedSize); 00110 // We split aggressively (for now; this could be a parameter). 00111 const size_t actualSize = super::getSize(obj); 00112 if (actualSize - requestedSize >= sizeof(typename super::Header) + sizeof(double)) { 00113 // Split the object. 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 // Now that we have a new successor (splitPiece), we need to 00121 // mark obj as in use. 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