MemoryPool::MemoryPool(bool shared, int rounding, int cutoff, int minAlloc) : roundingSize(rounding), threshold(cutoff), minAllocation(minAlloc), threadShared(shared), pool_destroying(false), stats(default_stats_group), parent(NULL) { const size_t vecSize = (cutoff + rounding) / rounding; init(allocRaw(vecSize * sizeof(void*)), vecSize); }
void *allocAligned( std::size_t size ) { // Calculate aligned pointer char * result = align( m_ptr ); // If not enough memory left in current pool, allocate a new pool if ( result + size > m_end ) { // Calculate required pool size (may be bigger than CLAS_DYNAMIC_POOL_SIZE) std::size_t pool_size = m_dynamicSize; if ( pool_size < size ) pool_size = size; // Allocate // 2 alignments required in worst case: one for header, one for actual allocation std::size_t alloc_size = sizeof( header ) + ( 2 * CLAS_ALIGNMENT - 2 ) + pool_size; char *raw_memory = allocRaw( alloc_size ); // Setup new pool in allocated memory char *pool = align( raw_memory ); header *new_header = reinterpret_cast<header *>( pool ); new_header->previous_begin = m_begin; m_begin = raw_memory; m_ptr = pool + sizeof( header ); m_end = raw_memory + alloc_size; // Calculate aligned pointer again using new pool result = align( m_ptr ); } // Update pool and return aligned pointer m_ptr = result + size; return result; }
MemBlock* MemoryPool::alloc(const size_t length) throw (OOM_EXCEPTION) { MutexLockGuard guard(mutex, "MemoryPool::alloc"); // If this is a small block, look for it there if (length <= threshold) { unsigned int slot = length / roundingSize; MemBlock* block; if (threadShared) { while (block = freeObjects[slot]) { if (freeObjects[slot].compareExchange(block, block->next)) { #ifdef MEM_DEBUG if (slot != block->length / roundingSize) corrupt("length trashed for block in slot"); #endif return block; } } } else { block = freeObjects[slot]; if (block) { freeObjects[slot] = (MemBlock*) block->pool; #ifdef MEM_DEBUG if (slot != block->length / roundingSize) corrupt("length trashed for block in slot"); #endif return block; } } // See if some other hunk has unallocated space to use MemSmallHunk* hunk; for (hunk = smallHunks; hunk; hunk = hunk->nextHunk) { if (length <= hunk->spaceRemaining) { MemBlock* block = (MemBlock*) hunk->memory; hunk->memory += length; hunk->spaceRemaining -= length; block->length = length; return block; } } // No good so far. Time for a new hunk hunk = (MemSmallHunk*) allocRaw(minAllocation); hunk->length = minAllocation - 16; hunk->nextHunk = smallHunks; smallHunks = hunk; size_t l = ROUNDUP(sizeof(MemSmallHunk), sizeof(double)); block = (MemBlock*) ((UCHAR*) hunk + l); hunk->spaceRemaining = minAllocation - length - l; hunk->memory = (UCHAR*) block + length; block->length = length; return block; } /* * OK, we've got a "big block" on on hands. To maximize confusing, the indicated * length of a free big block is the length of MemHeader plus body, explicitly * excluding the MemFreeBlock and MemBigHeader fields. [MemHeader::length] <---- MemBlock ----> *--------------*----------*---------* | MemBigHeader | MemHeader | Body | *--------------*----------*---------* <---- MemBigObject -----> *--------------*----------*---------------* | MemBigHeader | MemHeader | MemFreeBlock | *--------------*----------*---------------* <--------------- MemFreeBlock ----------> */ MemFreeBlock* freeBlock; for (freeBlock = freeBlocks.nextLarger; freeBlock != &freeBlocks; freeBlock = freeBlock->nextLarger) { if (freeBlock->memHeader.length >= length) { remove(freeBlock); MemBlock* block = (MemBlock*) &freeBlock->memHeader; // Compute length (MemHeader + body) for new free block unsigned int tail = block->length - length; // If there isn't room to split off a new free block, allocate the whole thing if (tail < sizeof(MemFreeBlock)) { block->pool = this; return block; } // Otherwise, chop up the block MemBigObject* newBlock = freeBlock; freeBlock = (MemFreeBlock*) ((UCHAR*) block + length); freeBlock->memHeader.length = tail - sizeof(MemBigObject); block->length = length; block->pool = this; if (freeBlock->next = newBlock->next) freeBlock->next->prior = freeBlock; newBlock->next = freeBlock; freeBlock->prior = newBlock; freeBlock->memHeader.pool = NULL; // indicate block is free insert(freeBlock); return block; } } // Didn't find existing space -- allocate new hunk size_t hunkLength = sizeof(MemBigHunk) + sizeof(MemBigHeader) + length; size_t freeSpace = 0; // If the hunk size is sufficient below minAllocation, allocate extra space if (hunkLength + sizeof(MemBigObject) + threshold < minAllocation) { hunkLength = minAllocation; //freeSpace = hunkLength - 2 * sizeof(MemBigObject) - length; freeSpace = hunkLength - sizeof(MemBigHunk) - 2 * sizeof(MemBigHeader) - length; } // Allocate the new hunk MemBigHunk* hunk = (MemBigHunk*) allocRaw(hunkLength); hunk->nextHunk = bigHunks; bigHunks = hunk; hunk->length = hunkLength; // Create the new block MemBigObject* newBlock = (MemBigObject*) &hunk->blocks; newBlock->prior = NULL; newBlock->next = NULL; MemBlock* block = (MemBlock*) &newBlock->memHeader; block->pool = this; block->length = length; // If there is space left over, create a free block if (freeSpace) { freeBlock = (MemFreeBlock*) ((UCHAR*) block + length); freeBlock->memHeader.length = freeSpace; freeBlock->memHeader.pool = NULL; freeBlock->next = NULL; freeBlock->prior = newBlock; newBlock->next = freeBlock; insert(freeBlock); } return block; }