📄 superpool.hpp
字号:
// Set current page. Previous current page is updated and added to // appropriate list. void setCurrPage(RecInfo& ri, PtrI pageI); // Get page with some free records and make it current. Takes head of // active or free list, or else gets free page from super pool. bool getAvailPage(RecInfo& ri); // Get free page from super pool and add it to record pool free list. // This is an expensive subroutine of getAvailPage(). PtrI getFreePage(RecInfo& ri); // Get new free page from the implementation. virtual PtrI getNewPage() = 0; // Set 3 size parameters, rounded to page size. If called before // init() then init() allocates the initial size. void setSizes(size_t initSize = 0, size_t incrSize = 0, size_t maxSize = 0); const Uint32 m_pageSize; const Uint32 m_pageBits; // implementation must set up these pointers void* m_memRoot; PageEnt* m_pageEnt; Uint32* m_typeCheck; Uint32 m_typeSeq; PageList m_pageList; size_t m_totalSize; size_t m_initSize; size_t m_incrSize; size_t m_maxSize; // Debugging. void verify(RecInfo& ri);};inline SuperPool::PageEnt&SuperPool::getPageEnt(PtrI pageI){ Uint32 ip = pageI >> (32 - m_pageBits); return m_pageEnt[ip];}inline void*SuperPool::getPageP(PtrI ptrI){ Int32 ip = (Int32)ptrI >> (32 - m_pageBits); my_ptrdiff_t sz = m_pageSize; void* pageP = (Uint8*)m_memRoot + ip * sz; return pageP;}inline Uint32SuperPool::makeCheckBits(Uint32 type){ Uint32 shift = 1 << SP_CHECK_LOG2; Uint32 mask = (1 << shift) - 1; return 1 + type % mask;}inline Uint32SuperPool::getCheckBits(PtrI pageI){ Uint32 ip = pageI >> (32 - m_pageBits); Uint32 xp = ip >> (5 - SP_CHECK_LOG2); Uint32 yp = ip & (1 << (5 - SP_CHECK_LOG2)) - 1; Uint32& w = m_typeCheck[xp]; Uint32 shift = 1 << SP_CHECK_LOG2; Uint32 mask = (1 << shift) - 1; // get Uint32 bits = (w >> yp * shift) & mask; return bits;}inline voidSuperPool::setCheckBits(PtrI pageI, Uint32 type){ Uint32 ip = pageI >> (32 - m_pageBits); Uint32 xp = ip >> (5 - SP_CHECK_LOG2); Uint32 yp = ip & (1 << (5 - SP_CHECK_LOG2)) - 1; Uint32& w = m_typeCheck[xp]; Uint32 shift = 1 << SP_CHECK_LOG2; Uint32 mask = (1 << shift) - 1; // set Uint32 bits = makeCheckBits(type); w &= ~(mask << yp * shift); w |= (bits << yp * shift);}inline void*SuperPool::getRecP(PtrI ptrI, RecInfo& ri){ const Uint32 recMask = (1 << (32 - m_pageBits)) - 1; PtrI pageI = ptrI & ~recMask;#if NDB_SP_VERIFY_LEVEL >= 1 Uint32 bits1 = getCheckBits(pageI); Uint32 bits2 = makeCheckBits(ri.m_recType); assert(bits1 == bits2);#endif void* pageP = getPageP(pageI); Uint32 ir = ptrI & recMask; void* recP = (Uint8*)pageP + ir * ri.m_recSize; return recP;}/* * HeapPool - SuperPool on heap (concrete class) * * A super pool based on malloc with memory root on the heap. This * pool type has 2 realistic uses: * * - a small pool with only initial malloc and pageBits set to match * - the big pool from which all heap allocations are done * * A "smart" malloc may break "ip" limit by using different VM areas for * different sized requests. For this reason malloc is done in units of * increment size if possible. Memory root is set to start of first * malloc. */class HeapPool : public SuperPool {public: // Describes malloc area. The areas are kept in singly linked list. // There is a list head and pointers to current and last area. struct Area { Area(); Area* m_nextArea; PtrI m_firstPageI; Uint32 m_currPage; Uint32 m_numPages; void* m_memory; }; // Constructor. HeapPool(Uint32 pageSize, Uint32 pageBits); // Initialize. virtual bool init(); // Destructor. virtual ~HeapPool(); // Use malloc to allocate more. bool allocMoreData(size_t size); // Get new page from current area. virtual PtrI getNewPage(); // List of malloc areas. Area m_areaHead; Area* m_currArea; Area* m_lastArea; // Fraction of malloc size to try if cannot get all in one. Uint32 m_mallocPart;};/* * RecordPool - record pool using one super pool instance (template) * * Documented under SuperPool. Satisfies ArrayPool interface. */template <class T>class RecordPool {public: // Constructor. RecordPool(SuperPool& superPool); // Destructor. ~RecordPool(); // Update pointer ptr.p according to i-value ptr.i. void getPtr(Ptr<T>& ptr); // Allocate record from the pool. bool seize(Ptr<T>& ptr); // Return record to the pool. void release(Ptr<T>& ptr); // todo variants of basic methods // Return all pages to super pool. The force flag is required if // there are any used records. void free(bool force); SuperPool& m_superPool; SuperPool::RecInfo m_recInfo;};template <class T>inlineRecordPool<T>::RecordPool(SuperPool& superPool) : m_superPool(superPool), m_recInfo(1 + superPool.m_typeSeq++, sizeof(T)){ SuperPool::RecInfo& ri = m_recInfo; assert(sizeof(T) == SP_ALIGN_SIZE(sizeof(T), sizeof(Uint32))); Uint32 maxUseCount = superPool.m_pageSize / sizeof(T); Uint32 sizeLimit = 1 << (32 - superPool.m_pageBits); if (maxUseCount >= sizeLimit) maxUseCount = sizeLimit; ri.m_maxUseCount = maxUseCount;}template <class T>inlineRecordPool<T>::~RecordPool(){ free(true);}template <class T>inline voidRecordPool<T>::getPtr(Ptr<T>& ptr){ void* recP = m_superPool.getRecP(ptr.i, m_recInfo); ptr.p = static_cast<T*>(recP);}template <class T>inline boolRecordPool<T>::seize(Ptr<T>& ptr){ SuperPool& sp = m_superPool; SuperPool::RecInfo& ri = m_recInfo; if (ri.m_currFreeRecI != RNIL || sp.getAvailPage(ri)) { SuperPool::PtrI recI = ri.m_currFreeRecI; void* recP = sp.getRecP(recI, ri); ri.m_currFreeRecI = *(Uint32*)recP; Uint32 useCount = ri.m_currUseCount; assert(useCount < ri.m_maxUseCount); ri.m_currUseCount = useCount + 1; ri.m_totalUseCount++; ptr.i = recI; ptr.p = static_cast<T*>(recP); return true; } return false;}template <class T>inline voidRecordPool<T>::release(Ptr<T>& ptr){ SuperPool& sp = m_superPool; SuperPool::RecInfo& ri = m_recInfo; const Uint32 recMask = (1 << (32 - sp.m_pageBits)) - 1; SuperPool::PtrI recI = ptr.i; SuperPool::PtrI pageI = recI & ~recMask; if (pageI != ri.m_currPageI) { sp.setCurrPage(ri, pageI); } void* recP = sp.getRecP(recI, ri); *(Uint32*)recP = ri.m_currFreeRecI; ri.m_currFreeRecI = recI; Uint32 useCount = ri.m_currUseCount; assert(useCount != 0); ri.m_currUseCount = useCount - 1; ri.m_totalUseCount--; ptr.i = RNIL; ptr.p = 0;}template <class T>inline voidRecordPool<T>::free(bool force){ SuperPool& sp = m_superPool; SuperPool::RecInfo& ri = m_recInfo; sp.setCurrPage(ri, RNIL); assert(force || ri.m_totalUseCount == 0); sp.movePages(sp.m_pageList, ri.m_freeList); sp.movePages(sp.m_pageList, ri.m_activeList); sp.movePages(sp.m_pageList, ri.m_fullList); ri.m_totalRecCount = 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -