📄 arraypool.hpp
字号:
/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifndef ARRAY_POOL_HPP#define ARRAY_POOL_HPP#include <ndb_global.h>#include "ndbd_malloc.hpp"#include <pc.hpp>#include <ErrorReporter.hpp>#include <NdbMem.h>#include <Bitmask.hpp>template <class T> class Array;template <class T> class SLList;template <class T> class DLList;template <class T> class DLHashTable;/** * Template class used for implementing an * pool of object (in an array with a free list) */template <class T>class ArrayPool {public: ArrayPool(); ~ArrayPool(); /** * Set the size of the pool * * Note, can currently only be called once */ bool setSize(Uint32 noOfElements, bool exit_on_error = true); inline Uint32 getNoOfFree() const { return noOfFree; } inline Uint32 getSize() const { return size; } /** * Update p value for ptr according to i value */ void getPtr(Ptr<T> &); void getPtr(ConstPtr<T> &) const; void getPtr(Ptr<T> &, bool CrashOnBoundaryError); void getPtr(ConstPtr<T> &, bool CrashOnBoundaryError) const; /** * Get pointer for i value */ T * getPtr(Uint32 i); const T * getConstPtr(Uint32 i) const; T * getPtr(Uint32 i, bool CrashOnBoundaryError); const T * getConstPtr(Uint32 i, bool CrashOnBoundaryError) const; /** * Update p & i value for ptr according to <b>i</b> value */ void getPtr(Ptr<T> &, Uint32 i); void getPtr(ConstPtr<T> &, Uint32 i) const; void getPtr(Ptr<T> &, Uint32 i, bool CrashOnBoundaryError); void getPtr(ConstPtr<T> &, Uint32 i, bool CrashOnBoundaryError) const; /** * Allocate an object from pool - update Ptr * * Return i */ bool seize(Ptr<T> &); /** * Allocate object <b>i</b> from pool - update Ptr */ bool seizeId(Ptr<T> &, Uint32 i); /** * Check if <b>i</b> is allocated. */ bool findId(Uint32 i) const; /** * Return an object to pool */ void release(Uint32 i); /** * Return an object to pool */ void release(Ptr<T> &);#ifdef ARRAY_GUARD /** * Checks if i is a correct seized record * * @note Since this is either an expensive method, * or needs bitmask stuff, this method is only * recommended for debugging. * */ bool isSeized(Uint32 i) const { if (i>=size) return false; return BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i); }#endifprotected: friend class Array<T>; friend class SLList<T>; friend class DLList<T>; friend class DLHashTable<T>; /** * Allocate <b>n</b> consecutive object from pool * return base */ Uint32 seizeN(Uint32 n); /** * Deallocate <b>n<b> consecutive object to pool * starting from base */ void releaseN(Uint32 base, Uint32 n);public: /** * Release a singel linked list in o(1) * @param first i-value of first element in list * @param last i-value of last element in list * @note nextPool must be used as next pointer in list */ void releaseList(Uint32 n, Uint32 first, Uint32 last); //private:#ifdef DEBUG Uint32 getNoOfFree2() const { Uint32 c2 = size; for(Uint32 i = 0; i<((size + 31)>> 5); i++){ Uint32 w = theAllocatedBitmask[i]; for(Uint32 j = 0; j<32; j++){ if((w & 1) == 1){ c2--; } w >>= 1; } } return c2; } Uint32 getNoOfFree3() const { Uint32 c = 0; Ptr<T> p; p.i = firstFree; while(p.i != RNIL){ c++; p.p = &theArray[p.i]; p.i = p.p->next; } return c; }#endifprotected: Uint32 firstFree; Uint32 size; Uint32 noOfFree; T * theArray; Uint32 bitmaskSz; Uint32 *theAllocatedBitmask;};template <class T>inlineArrayPool<T>::ArrayPool(){ firstFree = RNIL; size = 0; noOfFree = 0; theArray = 0;#ifdef ARRAY_GUARD theAllocatedBitmask = 0;#endif}template <class T>inlineArrayPool<T>::~ArrayPool(){ if(theArray != 0){ ndbd_free(theArray, size * sizeof(T)); theArray = 0;#ifdef ARRAY_GUARD delete []theAllocatedBitmask; theAllocatedBitmask = 0;#endif }} /** * Set the size of the pool * * Note, can currently only be called once */template <class T>inlineboolArrayPool<T>::setSize(Uint32 noOfElements, bool exit_on_error){ if(size == 0){ if(noOfElements == 0) return true; theArray = (T *)ndbd_malloc(noOfElements * sizeof(T)); if(theArray == 0) { if (!exit_on_error) return false; ErrorReporter::handleAssert("ArrayPool<T>::setSize malloc failed", __FILE__, __LINE__, NDBD_EXIT_MEMALLOC); return false; // not reached } size = noOfElements; noOfFree = noOfElements; /** * Set next pointers */ T * t = &theArray[0]; for(Uint32 i = 0; i<size; i++){ t->nextPool = (i + 1); t++; } theArray[size-1].nextPool = RNIL; firstFree = 0;#ifdef ARRAY_GUARD bitmaskSz = (noOfElements + 31) >> 5; theAllocatedBitmask = new Uint32[bitmaskSz]; BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask);#endif return true; } if (!exit_on_error) return false; ErrorReporter::handleAssert("ArrayPool<T>::setSize called twice", __FILE__, __LINE__); return false; // not reached} template <class T>inlinevoidArrayPool<T>::getPtr(Ptr<T> & ptr){ Uint32 i = ptr.i; if(i < size){ ptr.p = &theArray[i];#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);#endif } else { ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); }}template <class T>inlinevoidArrayPool<T>::getPtr(ConstPtr<T> & ptr) const { Uint32 i = ptr.i; if(i < size){ ptr.p = &theArray[i];#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);#endif } else { ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); }}template <class T>inlinevoidArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i){ ptr.i = i; if(i < size){ ptr.p = &theArray[i];#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);#endif } else { ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); }}template <class T>inlinevoidArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i) const { ptr.i = i; if(i < size){ ptr.p = &theArray[i];#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);#endif } else { ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); }} template <class T>inlineT * ArrayPool<T>::getPtr(Uint32 i){ if(i < size){#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return &theArray[i]; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); return 0;#else return &theArray[i];#endif } else { ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); return 0; }}template <class T>inlineconst T * ArrayPool<T>::getConstPtr(Uint32 i) const { if(i < size){#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return &theArray[i]; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); return 0;#else return &theArray[i];#endif } else { ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__); return 0; }}template <class T>inlinevoidArrayPool<T>::getPtr(Ptr<T> & ptr, bool CrashOnBoundaryError){ Uint32 i = ptr.i; if(i < size){ ptr.p = &theArray[i];#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);#endif } else { ptr.i = RNIL; }}template <class T>inlinevoidArrayPool<T>::getPtr(ConstPtr<T> & ptr, bool CrashOnBoundaryError) const { Uint32 i = ptr.i; if(i < size){ ptr.p = &theArray[i];#ifdef ARRAY_GUARD if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)) return; /** * Getting a non-seized element */ ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);#endif } else { ptr.i = RNIL; }}template <class T>inlinevoidArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i, bool CrashOnBoundaryError){ ptr.i = i; if(i < size){ ptr.p = &theArray[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -