123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- #ifndef CC_ALLOCATOR_STRATEGY_FIXED_BLOCK_H
- #define CC_ALLOCATOR_STRATEGY_FIXED_BLOCK_H
- #include <stdint.h>
- #include <vector>
- #include <typeinfo>
- #include <sstream>
- #include "base/allocator/CCAllocatorBase.h"
- #include "base/allocator/CCAllocatorMacros.h"
- #include "base/allocator/CCAllocatorGlobal.h"
- #include "base/allocator/CCAllocatorMutex.h"
- #include "base/allocator/CCAllocatorDiagnostics.h"
- NS_CC_BEGIN
- NS_CC_ALLOCATOR_BEGIN
- template <size_t _block_size, size_t _alignment = 16, typename lock_traits = locking_semantics>
- class AllocatorStrategyFixedBlock
- : public AllocatorBase
- , public lock_traits
- {
- public:
-
- static const size_t block_size = _block_size;
- static const size_t alignment = _alignment;
-
- AllocatorStrategyFixedBlock(const char* tag = nullptr, size_t pageSize = 100)
- : _list(nullptr)
- , _pages(nullptr)
- , _pageSize(pageSize)
- , _allocated(0)
- {
- #if CC_ENABLE_ALLOCATOR_DIAGNOSTICS
- _highestCount = 0;
- AllocatorDiagnostics::instance()->trackAllocator(this);
- AllocatorBase::setTag(tag ? tag : typeid(AllocatorStrategyFixedBlock).name());
- #endif
- }
-
- virtual ~AllocatorStrategyFixedBlock()
- {
- #if CC_ENABLE_ALLOCATOR_DIAGNOSTICS
- AllocatorDiagnostics::instance()->untrackAllocator(this);
- #endif
- do
- {
- intptr_t* page = (intptr_t*)_pages;
- intptr_t* next = (intptr_t*)*page;
- ccAllocatorGlobal.deallocate(page);
- _pages = (void*)next;
- }
- while (_pages);
- }
-
-
-
-
-
- CC_ALLOCATOR_INLINE void* allocate(size_t size)
- {
- CC_ASSERT(block_size == size);
- #ifdef FALLBACK_TO_GLOBAL
- return ccAllocatorGlobal.allocate(size);
- #else
- lock_traits::lock();
- auto r = pop_front();
- lock_traits::unlock();
- return r;
- #endif
- }
-
-
- CC_ALLOCATOR_INLINE void deallocate(void* address, size_t size = 0)
- {
- CC_ASSERT(0 == size || block_size == size);
- #ifdef FALLBACK_TO_GLOBAL
- ccAllocatorGlobal.deallocate(address);
- #else
- lock_traits::lock();
- push_front(address);
- lock_traits::unlock();
- #endif
- }
-
-
-
-
- CC_ALLOCATOR_INLINE bool owns(const void* const address)
- {
- #ifdef FALLBACK_TO_GLOBAL
- return true;
- #else
- lock_traits::lock();
-
- const uint8_t* const a = (const uint8_t* const)address;
- const uint8_t* p = (uint8_t*)_pages;
- const size_t pSize = pageSize();
- while (p)
- {
- if (a >= p && a < (p + pSize))
- {
- lock_traits::unlock();
- return true;
- }
- p = (uint8_t*)(*(uintptr_t*)p);
- }
- lock_traits::unlock();
- return false;
- #endif
- }
-
- #if CC_ENABLE_ALLOCATOR_DIAGNOSTICS
- std::string diagnostics() const
- {
- std::stringstream s;
- s << AllocatorBase::tag() << " initial:" << _pageSize << " count:" << _allocated << " highest:" << _highestCount << "\n";
- return s.str();
- }
- size_t _highestCount;
- #endif
-
- protected:
-
-
-
- CC_ALLOCATOR_INLINE void push_front(void* block)
- {
- CC_ASSERT(block);
- CC_ASSERT(block_size < AllocatorBase::kDefaultAlignment || 0 == ((intptr_t)block & (AllocatorBase::kDefaultAlignment - 1)));
- #if COCOS2D_DEBUG
-
- CC_ASSERT(true == owns(block));
- #endif
-
- if (nullptr == _list)
- {
- _list = block;
- *(uintptr_t*)block = 0;
- }
- else
- {
- uintptr_t* p = (uintptr_t*)(block);
- *p = (uintptr_t)_list;
- _list = block;
- }
- CC_ASSERT(_allocated > 0);
- --_allocated;
- }
-
-
-
-
-
-
- CC_ALLOCATOR_INLINE void* pop_front()
- {
- if (nullptr == _list)
- {
- allocatePage();
- }
- auto next = (void*)*(uintptr_t*)_list;
- auto block = _list;
- _list = next;
- ++_allocated;
- #if CC_ENABLE_ALLOCATOR_DIAGNOSTICS
- if (_allocated > _highestCount)
- _highestCount = _allocated;
- #endif
- CC_ASSERT(block_size < AllocatorBase::kDefaultAlignment || 0 == ((intptr_t)block & (AllocatorBase::kDefaultAlignment - 1)));
- return block;
- }
-
- protected:
-
-
- size_t pageSize() const
- {
- return AllocatorBase::kDefaultAlignment + AllocatorBase::nextPow2BlockSize(block_size) * _pageSize;
- }
-
-
-
- CC_ALLOCATOR_INLINE void allocatePage()
- {
- uint8_t* p = (uint8_t*)AllocatorBase::aligned(ccAllocatorGlobal.allocate(pageSize()));
- intptr_t* page = (intptr_t*)p;
- if (nullptr == _pages)
- {
- _pages = page;
- *page = 0;
- }
- else
- {
- *page = (intptr_t)_pages;
- _pages = page;
- }
-
- p += AllocatorBase::kDefaultAlignment;
-
- _allocated += _pageSize;
- size_t aligned_size = AllocatorBase::nextPow2BlockSize(block_size);
- uint8_t* block = (uint8_t*)p;
- for (unsigned int i = 0; i < _pageSize; ++i, block += aligned_size)
- {
- push_front(block);
- }
- }
-
- protected:
-
-
- void* _list;
-
-
- void* _pages;
-
-
- size_t _pageSize;
-
-
- size_t _allocated;
- };
- NS_CC_ALLOCATOR_END
- NS_CC_END
- #endif
|