123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*-
- * 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 <typename T, size_t BlockSize>
- inline typename MemoryPool<T, BlockSize>::size_type
- MemoryPool<T, BlockSize>::padPointer(data_pointer_ p, size_type align)
- const noexcept
- {
- uintptr_t result = reinterpret_cast<uintptr_t>(p);
- return ((align - result) % align);
- }
- template <typename T, size_t BlockSize>
- MemoryPool<T, BlockSize>::MemoryPool()
- noexcept
- {
- currentBlock_ = nullptr;
- currentSlot_ = nullptr;
- lastSlot_ = nullptr;
- freeSlots_ = nullptr;
- }
- template <typename T, size_t BlockSize>
- MemoryPool<T, BlockSize>::MemoryPool(const MemoryPool& memoryPool)
- noexcept :
- MemoryPool()
- {}
- template <typename T, size_t BlockSize>
- MemoryPool<T, BlockSize>::MemoryPool(MemoryPool&& memoryPool)
- noexcept
- {
- currentBlock_ = memoryPool.currentBlock_;
- memoryPool.currentBlock_ = nullptr;
- currentSlot_ = memoryPool.currentSlot_;
- lastSlot_ = memoryPool.lastSlot_;
- freeSlots_ = memoryPool.freeSlots;
- }
- template <typename T, size_t BlockSize>
- template<class U>
- MemoryPool<T, BlockSize>::MemoryPool(const MemoryPool<U>& memoryPool)
- noexcept :
- MemoryPool()
- {}
- template <typename T, size_t BlockSize>
- MemoryPool<T, BlockSize>&
- MemoryPool<T, BlockSize>::operator=(MemoryPool&& memoryPool)
- noexcept
- {
- if (this != &memoryPool)
- {
- std::swap(currentBlock_, memoryPool.currentBlock_);
- currentSlot_ = memoryPool.currentSlot_;
- lastSlot_ = memoryPool.lastSlot_;
- freeSlots_ = memoryPool.freeSlots;
- }
- return *this;
- }
- template <typename T, size_t BlockSize>
- MemoryPool<T, BlockSize>::~MemoryPool()
- noexcept
- {
- slot_pointer_ curr = currentBlock_;
- while (curr != nullptr) {
- slot_pointer_ prev = curr->next;
- operator delete(reinterpret_cast<void*>(curr));
- curr = prev;
- }
- }
- template <typename T, size_t BlockSize>
- inline typename MemoryPool<T, BlockSize>::pointer
- MemoryPool<T, BlockSize>::address(reference x)
- const noexcept
- {
- return &x;
- }
- template <typename T, size_t BlockSize>
- inline typename MemoryPool<T, BlockSize>::const_pointer
- MemoryPool<T, BlockSize>::address(const_reference x)
- const noexcept
- {
- return &x;
- }
- template <typename T, size_t BlockSize>
- void
- MemoryPool<T, BlockSize>::allocateBlock()
- {
- // Allocate space for the new block and store a pointer to the previous one
- data_pointer_ newBlock = reinterpret_cast<data_pointer_>
- (operator new(BlockSize));
- reinterpret_cast<slot_pointer_>(newBlock)->next = currentBlock_;
- currentBlock_ = reinterpret_cast<slot_pointer_>(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<slot_pointer_>(body + bodyPadding);
- lastSlot_ = reinterpret_cast<slot_pointer_>
- (newBlock + BlockSize - sizeof(slot_type_) + 1);
- }
- template <typename T, size_t BlockSize>
- inline typename MemoryPool<T, BlockSize>::pointer
- MemoryPool<T, BlockSize>::allocate(size_type /*n*/, const_pointer /*hint*/)
- {
- if (freeSlots_ != nullptr) {
- pointer result = reinterpret_cast<pointer>(freeSlots_);
- freeSlots_ = freeSlots_->next;
- return result;
- }
- else {
- if (currentSlot_ >= lastSlot_)
- allocateBlock();
- return reinterpret_cast<pointer>(currentSlot_++);
- }
- }
- template <typename T, size_t BlockSize>
- inline void
- MemoryPool<T, BlockSize>::deallocate(pointer p, size_type /*n*/)
- {
- if (p != nullptr) {
- reinterpret_cast<slot_pointer_>(p)->next = freeSlots_;
- freeSlots_ = reinterpret_cast<slot_pointer_>(p);
- }
- }
- template <typename T, size_t BlockSize>
- inline typename MemoryPool<T, BlockSize>::size_type
- MemoryPool<T, BlockSize>::max_size()
- const noexcept
- {
- size_type maxBlocks = -1 / BlockSize;
- return (BlockSize - sizeof(data_pointer_)) / sizeof(slot_type_) * maxBlocks;
- }
- template <typename T, size_t BlockSize>
- template <class U, class... Args>
- inline void
- MemoryPool<T, BlockSize>::construct(U* p, Args&&... args)
- {
- new (p) U (std::forward<Args>(args)...);
- }
- template <typename T, size_t BlockSize>
- template <class U>
- inline void
- MemoryPool<T, BlockSize>::destroy(U* p)
- {
- p->~U();
- }
- template <typename T, size_t BlockSize>
- template <class... Args>
- inline typename MemoryPool<T, BlockSize>::pointer
- MemoryPool<T, BlockSize>::newElement(Args&&... args)
- {
- pointer result = allocate();
- construct<value_type>(result, std::forward<Args>(args)...);
- return result;
- }
- template <typename T, size_t BlockSize>
- inline void
- MemoryPool<T, BlockSize>::deleteElement(pointer p)
- {
- if (p != nullptr) {
- p->~value_type();
- deallocate(p);
- }
- }
- #endif // MEMORY_BLOCK_TCC
|