Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/coalesceheap.h
Ir a la documentación de este archivo.
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
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'