/*- * Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #ifndef MEMORY_BLOCK_TCC #define MEMORY_BLOCK_TCC template inline typename MemoryPool::size_type MemoryPool::padPointer(data_pointer_ p, size_type align) const noexcept { uintptr_t result = reinterpret_cast(p); return ((align - result) % align); } template MemoryPool::MemoryPool() noexcept { currentBlock_ = nullptr; currentSlot_ = nullptr; lastSlot_ = nullptr; freeSlots_ = nullptr; } template MemoryPool::MemoryPool(const MemoryPool& memoryPool) noexcept : MemoryPool() {} template MemoryPool::MemoryPool(MemoryPool&& memoryPool) noexcept { currentBlock_ = memoryPool.currentBlock_; memoryPool.currentBlock_ = nullptr; currentSlot_ = memoryPool.currentSlot_; lastSlot_ = memoryPool.lastSlot_; freeSlots_ = memoryPool.freeSlots; } template template MemoryPool::MemoryPool(const MemoryPool& memoryPool) noexcept : MemoryPool() {} template MemoryPool& MemoryPool::operator=(MemoryPool&& memoryPool) noexcept { if (this != &memoryPool) { std::swap(currentBlock_, memoryPool.currentBlock_); currentSlot_ = memoryPool.currentSlot_; lastSlot_ = memoryPool.lastSlot_; freeSlots_ = memoryPool.freeSlots; } return *this; } template MemoryPool::~MemoryPool() noexcept { slot_pointer_ curr = currentBlock_; while (curr != nullptr) { slot_pointer_ prev = curr->next; operator delete(reinterpret_cast(curr)); curr = prev; } } template inline typename MemoryPool::pointer MemoryPool::address(reference x) const noexcept { return &x; } template inline typename MemoryPool::const_pointer MemoryPool::address(const_reference x) const noexcept { return &x; } template void MemoryPool::allocateBlock() { // Allocate space for the new block and store a pointer to the previous one data_pointer_ newBlock = reinterpret_cast (operator new(BlockSize)); reinterpret_cast(newBlock)->next = currentBlock_; currentBlock_ = reinterpret_cast(newBlock); // Pad block body to staisfy the alignment requirements for elements data_pointer_ body = newBlock + sizeof(slot_pointer_); size_type bodyPadding = padPointer(body, alignof(slot_type_)); currentSlot_ = reinterpret_cast(body + bodyPadding); lastSlot_ = reinterpret_cast (newBlock + BlockSize - sizeof(slot_type_) + 1); } template inline typename MemoryPool::pointer MemoryPool::allocate(size_type n, const_pointer hint) { if (freeSlots_ != nullptr) { pointer result = reinterpret_cast(freeSlots_); freeSlots_ = freeSlots_->next; return result; } else { if (currentSlot_ >= lastSlot_) allocateBlock(); return reinterpret_cast(currentSlot_++); } } template inline void MemoryPool::deallocate(pointer p, size_type n) { if (p != nullptr) { reinterpret_cast(p)->next = freeSlots_; freeSlots_ = reinterpret_cast(p); } } template inline typename MemoryPool::size_type MemoryPool::max_size() const noexcept { size_type maxBlocks = -1 / BlockSize; return (BlockSize - sizeof(data_pointer_)) / sizeof(slot_type_) * maxBlocks; } template template inline void MemoryPool::construct(U* p, Args&&... args) { new (p) U (std::forward(args)...); } template template inline void MemoryPool::destroy(U* p) { p->~U(); } template template inline typename MemoryPool::pointer MemoryPool::newElement(Args&&... args) { pointer result = allocate(); construct(result, std::forward(args)...); return result; } template inline void MemoryPool::deleteElement(pointer p) { if (p != nullptr) { p->~value_type(); deallocate(p); } } #endif // MEMORY_BLOCK_TCC