/****************************************************************** * Core Library Version 1.6, June 2003 * Copyright (c) 1995-2002 Exact Computation Project * * File: MemoryPool.h * Synopsis: * a memory pool template class. * * Written by * Chee Yap * Zilin Du * Sylvain Pion * * WWW URL: http://cs.nyu.edu/exact/ * Email: exact@cs.nyu.edu * * $Id$ *****************************************************************/ #ifndef CORE_MEMORYPOOL_H #define CORE_MEMORYPOOL_H #ifdef CORE_DISABLE_MEMORY_POOL #define CORE_MEMORY(T) #else #include #include CORE_BEGIN_NAMESPACE #define CORE_EXPANSION_SIZE 1024 template class MemoryPool { public: MemoryPool(); ~MemoryPool(); // allocate a T element from the free list. void* allocate(size_t) { if (next == NULL) expandFreeList(); MemoryPool *head = next; next = head->next; nCount --; return head; } // return a T element to the free list. void free(void* doomed) { if (doomed == NULL) return; MemoryPool *head = static_cast *>(doomed); head->next = next; next = head; nCount ++; //if (nCount % 2048 == 0) { // std::cout << nCount << " of " << typeid(T).name() // << "(size=" << sizeof(T) << ")" << ", total=" // << (nCount>>10)*sizeof(T) << "KB" << std::endl; // releaseFreeList(1024); //} } // Access the corresponding static global allocator. static MemoryPool& global_allocator() { return memPool; } private: // next element on the free list. MemoryPool *next; // expand free list. void expandFreeList(int howMany = CORE_EXPANSION_SIZE); // release free list. void releaseFreeList(int howMany); // number of the free element. int nCount; // Static global allocator. static MemoryPool memPool; }; template MemoryPool MemoryPool::memPool; template MemoryPool::MemoryPool() : next(NULL), nCount(0) {} template MemoryPool::~MemoryPool() { releaseFreeList(nCount); } template void MemoryPool::releaseFreeList(int howMany) { int i; MemoryPool *nextPtr = next; for (i=0; (nextPtr != NULL && i < howMany); i++) { nextPtr = next; next = nextPtr->next; ::delete[] reinterpret_cast(nextPtr); //::delete[] reinterpret_cast(nextPtr); //::delete nextPtr; } nCount -= i; /* in case failure */ } template void MemoryPool::expandFreeList(int howMany) { size_t size = sizeof(T); if ( size < sizeof(MemoryPool *) ) size = sizeof(MemoryPool *); char* p = ::new char[size]; if (p == NULL) std::cerr << "Out of Memory!!!" << std::endl; MemoryPool *runner = reinterpret_cast *>(p); next = runner; for (int i=0; inext = reinterpret_cast *>(p); runner = runner->next; } runner->next = NULL; nCount += howMany; /* Below implementation will be faster, but if we use it, there is no way to free allocated memory except when the program terminated. */ /* char* p = new char[size*howMany]; if (p == NULL) std::cerr << "Out of Memory!!!" << std::endl; MemoryPool *runner = reinterpret_cast *>(p); next = runner; for (int i=0; inext = reinterpret_cast *>(p); runner = runner->next; } runner->next = NULL; */ } CORE_END_NAMESPACE // You can put the following macro in (the public part of) the body of a class // to make it use the memory pool. #define CORE_MEMORY(T) \ void *operator new( size_t size) \ { return MemoryPool::global_allocator().allocate(size); } \ void operator delete( void *p, size_t ) \ { MemoryPool::global_allocator().free(p); } #endif #endif