/* -*- C++ -*- */ /* Heap Layers: An Extensible Memory Allocation Infrastructure Copyright (C) 2000-2005 by Emery Berger http://www.cs.umass.edu/~emery emery@cs.umass.edu This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _XALLOCHEAP_H_ #define _XALLOCHEAP_H_ namespace HL { template class XallocHeap : public SuperHeap { public: inline XallocHeap (void) { start_of_array = (char *) SuperHeap::malloc (ArenaSize); end_of_array = start_of_array + align(sizeof(Nuggie)); size_lval(end_of_array) = 0; last_block = NULL; } inline ~XallocHeap (void) { SuperHeap::free (start_of_array); } inline void * malloc (size_t size) { char * old_end_of_array = end_of_array; end_of_array += align(size + sizeof(Nuggie)); if (old_end_of_array + size >= start_of_array + ArenaSize) { // We're out of memory. return NULL; } size_lval(end_of_array) = end_of_array - old_end_of_array; clear_use(end_of_array); /* this is not necessary, cause it will be zero */ set_use(old_end_of_array); last_block = old_end_of_array; return old_end_of_array; } inline void free (void * ptr) { char * p = (char *) ptr; char * q; /* At this point we could check that the in_use bit for this block is set, and also check that the size is right */ clear_use(p); /* mark this block as unused */ if (p == last_block) { while (1) { q = prev_block(p); if (q == p) { last_block = NULL; end_of_array = p; break; /* only happens when we get to the beginning */ } if (in_use(q)) { last_block = q; end_of_array = p; break; } p = q; } } } private: static inline size_t& size_lval (char * x) { return (((Nuggie *)(((char *)x) - sizeof(Nuggie)))->size); } static inline char * prev_block (char * x) { return (((char *) x) - (size_lval(x) & (~1))); } static inline int in_use (char * x) { return (size_lval(x) & (1)); } static inline void set_use (char * x) { (size_lval(x) |= (1)); } static inline void clear_use (char * x) { (size_lval(x) &= (~1)); } class Nuggie { public: size_t size; }; inline static size_t align (int sz) { return (sz + (sizeof(double) - 1)) & ~(sizeof(double) - 1); } char * end_of_array; char * start_of_array; char * last_block; }; }; #endif