Allocate memory of a given size (in bytes) and return a pointer to the allocated memory.
| 99 | // Allocate memory of a given size (in bytes) and return a pointer to the |
| 100 | // allocated memory. |
| 101 | void* PoolAllocator::allocate(size_t size) { |
| 102 | |
| 103 | // Lock the method with a mutex |
| 104 | std::lock_guard<std::mutex> lock(mMutex); |
| 105 | |
| 106 | assert(size > 0); |
| 107 | |
| 108 | // We cannot allocate zero bytes |
| 109 | if (size == 0) return nullptr; |
| 110 | |
| 111 | #ifndef NDEBUG |
| 112 | mNbTimesAllocateMethodCalled++; |
| 113 | #endif |
| 114 | |
| 115 | // If we need to allocate more than the maximum memory unit size |
| 116 | if (size > MAX_UNIT_SIZE) { |
| 117 | |
| 118 | // Allocate memory using default allocation |
| 119 | void* allocatedMemory = mBaseAllocator.allocate(size); |
| 120 | |
| 121 | // Check that allocated memory is 16-bytes aligned |
| 122 | assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0); |
| 123 | |
| 124 | return allocatedMemory; |
| 125 | } |
| 126 | |
| 127 | // Get the index of the heap that will take care of the allocation request |
| 128 | int indexHeap = mMapSizeToHeapIndex[size]; |
| 129 | assert(indexHeap >= 0 && indexHeap < NB_HEAPS); |
| 130 | |
| 131 | // If there still are free memory units in the corresponding heap |
| 132 | if (mFreeMemoryUnits[indexHeap] != nullptr) { |
| 133 | |
| 134 | // Return a pointer to the memory unit |
| 135 | MemoryUnit* unit = mFreeMemoryUnits[indexHeap]; |
| 136 | mFreeMemoryUnits[indexHeap] = unit->nextUnit; |
| 137 | |
| 138 | void* allocatedMemory = static_cast<void*>(unit); |
| 139 | |
| 140 | // Check that allocated memory is 16-bytes aligned |
| 141 | assert(reinterpret_cast<uintptr_t>(allocatedMemory) % GLOBAL_ALIGNMENT == 0); |
| 142 | |
| 143 | return allocatedMemory; |
| 144 | } |
| 145 | else { // If there is no more free memory units in the corresponding heap |
| 146 | |
| 147 | // If we need to allocate more memory to contains the blocks |
| 148 | if (mNbCurrentMemoryBlocks == mNbAllocatedMemoryBlocks) { |
| 149 | |
| 150 | // Allocate more memory to contain the blocks |
| 151 | MemoryBlock* currentMemoryBlocks = mMemoryBlocks; |
| 152 | mNbAllocatedMemoryBlocks += 64; |
| 153 | mMemoryBlocks = static_cast<MemoryBlock*>(mBaseAllocator.allocate(mNbAllocatedMemoryBlocks * sizeof(MemoryBlock))); |
| 154 | memcpy(mMemoryBlocks, currentMemoryBlocks, mNbCurrentMemoryBlocks * sizeof(MemoryBlock)); |
| 155 | memset(mMemoryBlocks + mNbCurrentMemoryBlocks, 0, 64 * sizeof(MemoryBlock)); |
| 156 | mBaseAllocator.release(currentMemoryBlocks, mNbCurrentMemoryBlocks * sizeof(MemoryBlock)); |
| 157 | } |
| 158 |