#ifndef __JLANG__JRAM__ #define __JLANG__JRAM__ #include #include "JLang/JException.hh" /** * \file * Auxiliary class to speed up new/delete operations of any class. * \author mdejong */ namespace JLANG {} namespace JPP { using namespace JLANG; } namespace JLANG { /** * Memory management for small objects. * This object allocator is optimised for speed at the cost of some memory overhead. */ class JRAM : public std::vector { private: const std::size_t BLOCK_SIZE; const std::size_t numberOfBlocks; std::vector memory; /** * Add memory. */ void addMemory() { unsigned char* buffer = new unsigned char[BLOCK_SIZE * numberOfBlocks]; if (buffer == NULL) { THROW(JException, "JRAM::allocate(): not enough space in memory."); } memory.push_back(buffer); const std::size_t size = this->size(); this->resize(size + numberOfBlocks); iterator q = this->begin(); std::advance(q, size); for ( ; q != this->end(); buffer += BLOCK_SIZE, ++q) { *q = buffer; } } public: /** * Constructor. * * \param block_size number of bytes * \param number_of_blocks number of blocks */ JRAM(const std::size_t block_size, const std::size_t number_of_blocks = 65536) : std::vector(), BLOCK_SIZE (block_size), numberOfBlocks(number_of_blocks) { addMemory(); } /** * Destructor. */ ~JRAM() { for (std::vector::iterator i = memory.begin(); i != memory.end(); ++i) { delete [] (*i); } } /** * Get total used RAM. * * \return number of bytes */ long long int getTotalRAM() { return this->size() * sizeof(void*) + memory.size() * BLOCK_SIZE * numberOfBlocks; } /** * Get total free RAM. * * \return number of bytes */ long long int getFreeRAM() { return this->size() * BLOCK_SIZE; } /** * Allocate memory. * * \return pointer to avaible memory */ inline void* allocate() { if (this->empty()) { addMemory(); } this->pop_back(); return *(this->end()); } /** * Deallocate memory. * * \param p pointer to memory to be freed */ inline void free(void* p) { this->push_back(p); } /** * Run garbage collector. */ void gc() { using namespace std; sort(this->begin(), this->end()); vector::iterator __end = memory.end(); for (vector::iterator i = memory.begin(); i != __end; ) { iterator p = lower_bound(this->begin(), this->end(), *i); iterator q = p + numberOfBlocks - 1; if (*p == *i && distance(q, this->end()) > 0 && ((unsigned char*) (*q) - (unsigned char*) *p) == (int) (BLOCK_SIZE * (numberOfBlocks - 1))) { iter_swap(i, --__end); this->erase(p,++q); } else { ++i; } } for (std::vector::iterator i = __end; i != memory.end(); ++i) { delete [] (*i); } memory.erase(__end, memory.end()); } private: JRAM(const JRAM&); JRAM(JRAM&&); JRAM& operator=(const JRAM&); JRAM& operator=(JRAM&&); }; } #endif