/*****************************************************************************/ /*! *\file memory_manager_context.h *\brief Stack-based memory manager * * Author: Clark Barrett * * Created: Thu Aug 3 21:39:07 2006 * *
* * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. * *
*/ /*****************************************************************************/ #ifndef _cvc3__include__memory_manager_context_h #define _cvc3__include__memory_manager_context_h #include #include "memory_manager.h" namespace CVC3 { /*****************************************************************************/ /*! *\class ContextMemoryManager *\brief ContextMemoryManager * * Author: Clark Barrett * * Created: Thu Aug 3 16:41:35 2006 * * Stack-based memory manager */ /*****************************************************************************/ class ContextMemoryManager :public MemoryManager { private: unsigned d_chunkSizeBytes; // #bytes in each chunk static std::vector s_freePages; std::vector d_chunkList; // Pointers to the beginning of each chunk // Pointers to the next free block of memory in the current chunk char* d_nextFree; // Pointer to end of current chunk (1 byte off the end) char* d_endChunk; // Index into chunk vector unsigned d_indexChunkList; // Stack of pointers to the next free block of memory in the current chunk std::vector d_nextFreeStack; // Stack of pointers to end of current chunk (1 byte off the end) std::vector d_endChunkStack; // Stack of indices into chunk vector std::vector d_indexChunkListStack; // Private methods void newChunk() { // Allocate new chunk DebugAssert(d_chunkList.size() > 0, "expected unempty list"); ++d_indexChunkList; DebugAssert(d_chunkList.size() == d_indexChunkList, "invariant violated"); if (s_freePages.empty()) { d_chunkList.push_back((char*)malloc(d_chunkSizeBytes)); } else { d_chunkList.push_back(s_freePages.back()); s_freePages.pop_back(); } d_nextFree = d_chunkList.back(); FatalAssert(d_nextFree != NULL, "Out of memory"); d_endChunk = d_nextFree + d_chunkSizeBytes; } public: // Constructor ContextMemoryManager(unsigned chunkSize = 16384) : d_chunkSizeBytes(chunkSize), d_indexChunkList(0) { if (s_freePages.empty()) { d_chunkList.push_back((char*)malloc(d_chunkSizeBytes)); } else { d_chunkList.push_back(s_freePages.back()); s_freePages.pop_back(); } d_nextFree = d_chunkList.back(); FatalAssert(d_nextFree != NULL, "Out of memory"); d_endChunk = d_nextFree + d_chunkSizeBytes; } // Destructor ~ContextMemoryManager() { while(!d_chunkList.empty()) { s_freePages.push_back(d_chunkList.back()); d_chunkList.pop_back(); } } void* newData(size_t size) { void* res = (void*)d_nextFree; d_nextFree += size; if (d_nextFree > d_endChunk) { newChunk(); res = (void*)d_nextFree; d_nextFree += size; DebugAssert(d_nextFree <= d_endChunk, "chunk not big enough"); } return res; } void deleteData(void* d) { } void push() { d_nextFreeStack.push_back(d_nextFree); d_endChunkStack.push_back(d_endChunk); d_indexChunkListStack.push_back(d_indexChunkList); } void pop() { d_nextFree = d_nextFreeStack.back(); d_nextFreeStack.pop_back(); d_endChunk = d_endChunkStack.back(); d_endChunkStack.pop_back(); while (d_indexChunkList > d_indexChunkListStack.back()) { s_freePages.push_back(d_chunkList.back()); d_chunkList.pop_back(); --d_indexChunkList; } d_indexChunkListStack.pop_back(); } static void garbageCollect(void) { while (!s_freePages.empty()) { free(s_freePages.back()); s_freePages.pop_back(); } } unsigned getMemory() { return d_chunkList.size() * d_chunkSizeBytes; } static unsigned getStaticMemory() { return s_freePages.size() * 16384; } }; // end of class ContextMemoryManager } #endif