19 #ifndef ARRAY_POOL_HPP
20 #define ARRAY_POOL_HPP
22 #include <ndb_global.h>
23 #include "ndbd_malloc.hpp"
27 #include <ErrorReporter.hpp>
29 #include <Bitmask.hpp>
34 template <
class T>
class Array;
53 bool setSize(Uint32 noOfElements,
bool align =
false,
bool exit_on_error =
true,
54 bool guard =
true, Uint32 paramId = 0);
55 bool set(T*, Uint32 cnt,
bool align =
false);
56 void clear() { theArray = 0; }
58 inline Uint32 getNoOfFree()
const {
62 inline Uint32 getSize()
const {
66 inline Uint32 getUsed()
const {
67 return size - noOfFree;
70 inline Uint32 getUsedHi()
const {
71 return size - noOfFreeMin;
74 inline void updateFreeMin(
void) {
75 if (noOfFree < noOfFreeMin)
76 noOfFreeMin = noOfFree;
79 inline void decNoFree(
void) {
85 inline void decNoFree(Uint32 cnt) {
86 assert(noOfFree >= cnt);
91 inline Uint32 getEntrySize()
const {
107 const T * getConstPtr(Uint32 i)
const;
108 T *
getPtr(Uint32 i,
bool CrashOnBoundaryError);
109 const T * getConstPtr(Uint32 i,
bool CrashOnBoundaryError)
const;
116 void getPtr(
Ptr<T> &, Uint32 i,
bool CrashOnBoundaryError);
134 bool findId(Uint32 i)
const;
155 bool isSeized(Uint32 i)
const {
156 if (i>=size)
return false;
168 Cache(Uint32 a0 = 512, Uint32 a1 = 256) { m_first_free = RNIL; m_free_cnt = 0; m_alloc_cnt = a0; m_max_free_cnt = a1; }
172 Uint32 m_max_free_cnt;
178 void (* unlock)(void);
184 void releaseList(
LockFun,
Cache&, Uint32
n, Uint32 first, Uint32 last);
186 void setChunkSize(Uint32 sz);
187 #ifdef ARRAY_CHUNK_GUARD
194 bool seizeChunk(Uint32 &
n,
Ptr<T> &);
195 void releaseChunk(Uint32
n, Uint32 first, Uint32 last);
198 friend class Array<T>;
219 void releaseList(Uint32
n, Uint32 first, Uint32 last);
223 Uint32 getNoOfFree2()
const {
225 for(Uint32 i = 0; i<((size + 31)>> 5); i++){
226 Uint32 w = theAllocatedBitmask[
i];
227 for(Uint32 j = 0; j<32; j++){
237 Uint32 getNoOfFree3()
const {
243 p.p = &theArray[p.i];
259 Uint32 *theAllocatedBitmask;
274 theAllocatedBitmask = 0;
283 ndbd_free(alloc_ptr,
size *
sizeof(T));
287 if (theAllocatedBitmask)
288 delete []theAllocatedBitmask;
289 theAllocatedBitmask = 0;
303 bool align,
bool exit_on_error,
bool guard, Uint32 paramId){
305 if(noOfElements == 0)
307 Uint64 real_size = (Uint64)noOfElements *
sizeof(T);
308 size_t req_size = (size_t)real_size;
309 Uint64 real_size_align = real_size +
sizeof(T);
310 size_t req_size_align = (size_t)real_size_align;
314 if((Uint64)req_size_align == real_size_align && req_size_align > 0)
315 alloc_ptr = ndbd_malloc(req_size_align);
316 UintPtr p = (UintPtr)alloc_ptr;
317 UintPtr mod = p %
sizeof(T);
320 p +=
sizeof(T) - mod;
324 else if((Uint64)req_size == real_size && req_size > 0)
325 theArray = (T *)(alloc_ptr = ndbd_malloc(req_size));
329 char errmsg[255] =
"ArrayPool<T>::setSize malloc failed";
337 "Malloc memory for %s failed", param_info.m_name);
340 ErrorReporter::handleAssert(errmsg,
341 __FILE__, __LINE__, NDBD_EXIT_MEMALLOC);
345 noOfFree = noOfElements;
346 noOfFreeMin = noOfElements;
351 T * t = &theArray[0];
352 for(Uint32 i = 0; i<
size; i++){
353 t->nextPool = (i + 1);
356 theArray[size-1].nextPool = RNIL;
362 bitmaskSz = (noOfElements + 31) >> 5;
363 theAllocatedBitmask =
new Uint32[bitmaskSz];
373 ErrorReporter::handleAssert(
"ArrayPool<T>::setSize called twice", __FILE__, __LINE__);
383 for (i = 0; i + sz <
size; i += sz)
385 theArray[
i].chunkSize = sz;
386 theArray[
i].lastChunk = i + sz - 1;
387 theArray[
i].nextChunk = i + sz;
390 theArray[
i].chunkSize = size -
i;
391 theArray[
i].lastChunk = size - 1;
392 theArray[
i].nextChunk = RNIL;
398 #ifdef ARRAY_CHUNK_GUARD
412 UintPtr p = (UintPtr)alloc_ptr;
413 UintPtr mod = p %
sizeof(T);
416 p +=
sizeof(T) - mod;
423 theArray = (T *)alloc_ptr;
431 ErrorReporter::handleAssert(
"ArrayPool<T>::set called twice",
441 if(likely (i <
size)){
442 ptr.p = &theArray[
i];
444 if (theAllocatedBitmask)
451 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
455 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
464 if(likely(i <
size)){
465 ptr.p = &theArray[
i];
467 if (theAllocatedBitmask)
474 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
478 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
487 if(likely(i <
size)){
488 ptr.p = &theArray[
i];
490 if (theAllocatedBitmask)
497 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
501 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
510 if(likely(i <
size)){
511 ptr.p = &theArray[
i];
513 if (theAllocatedBitmask)
520 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
524 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
532 if(likely(i <
size)){
534 if (theAllocatedBitmask)
541 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
547 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
556 if(likely(i <
size)){
558 if (theAllocatedBitmask)
565 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
571 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
581 if(likely(i <
size)){
582 ptr.p = &theArray[
i];
584 if (theAllocatedBitmask)
591 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
604 if(likely(i <
size)){
605 ptr.p = &theArray[
i];
607 if (theAllocatedBitmask)
614 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
627 if(likely(i <
size)){
628 ptr.p = &theArray[
i];
630 if (theAllocatedBitmask)
637 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
649 bool CrashOnBoundaryError)
const {
651 if(likely(i <
size)){
652 ptr.p = &theArray[
i];
654 if (theAllocatedBitmask)
661 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
673 if(likely(i <
size)){
675 if (theAllocatedBitmask)
682 ErrorReporter::handleAssert(
"ArrayPool<T>::getPtr", __FILE__, __LINE__);
696 if(likely(i <
size)){
698 if (theAllocatedBitmask)
705 ErrorReporter::handleAssert(
"ArrayPool<T>::getConstPtr", __FILE__,__LINE__);
725 assert(chunk ==
false);
728 Uint32 ff = firstFree;
730 firstFree = theArray[ff].nextPool;
733 ptr.p = &theArray[ff];
735 if (theAllocatedBitmask)
745 ErrorReporter::handleAssert(
"ArrayPool<T>::seize", __FILE__, __LINE__);
763 assert(chunk ==
false);
766 Uint32 ff = firstFree;
768 while(ff != i && ff != RNIL){
770 ff = theArray[ff].nextPool;
775 firstFree = theArray[ff].nextPool;
777 theArray[prev].nextPool = theArray[ff].nextPool;
780 ptr.p = &theArray[ff];
782 if (theAllocatedBitmask)
792 ErrorReporter::handleAssert(
"ArrayPool<T>::seizeId", __FILE__, __LINE__);
811 Uint32 ff = firstFree;
812 while(ff != i && ff != RNIL){
813 ff = theArray[ff].nextPool;
822 assert(chunk ==
false);
825 Uint32 curr = firstFree;
828 while(sz < n && curr != RNIL){
829 if(theArray[curr].nextPool == (curr + 1)){
835 curr = theArray[curr].nextPool;
840 const Uint32 base = curr -
n;
841 if(base == firstFree){
844 theArray[prev].nextPool = curr;
849 if (theAllocatedBitmask)
851 for(Uint32 j = base; j<curr; j++){
858 ErrorReporter::handleAssert(
"ArrayPool<T>::seize", __FILE__, __LINE__);
872 assert(chunk ==
false);
875 Uint32 curr = firstFree;
879 curr = theArray[curr].nextPool;
881 if(curr == firstFree){
884 theArray[prev].nextPool = base;
886 const Uint32 end = base +
n;
887 for(Uint32 i = base; i<end; i++){
889 if (theAllocatedBitmask)
897 ErrorReporter::handleAssert(
"ArrayPool<T>::release", __FILE__, __LINE__);
902 theArray[
i].nextPool = i + 1;
904 theArray[end-1].nextPool = curr;
914 assert(chunk ==
false);
920 Uint32 ff = firstFree;
922 theArray[last].nextPool = ff;
926 if (theAllocatedBitmask)
929 for(Uint32 i = 0; i<
n; i++){
936 ErrorReporter::handleAssert(
"ArrayPool<T>::releaseList",
940 tmp = theArray[tmp].nextPool;
946 ErrorReporter::handleAssert(
"ArrayPool<T>::releaseList", __FILE__, __LINE__);
958 assert(chunk ==
false);
962 if(likely(i <
size)){
963 Uint32 ff = firstFree;
964 theArray[
i].nextPool = ff;
968 if (theAllocatedBitmask)
978 ErrorReporter::handleAssert(
"ArrayPool<T>::release", __FILE__, __LINE__);
984 ErrorReporter::handleAssert(
"ArrayPool<T>::release", __FILE__, __LINE__);
996 assert(chunk ==
false);
1000 if(likely(i <
size)){
1001 Uint32 ff = firstFree;
1002 theArray[
i].nextPool = ff;
1006 if (theAllocatedBitmask)
1017 ErrorReporter::handleAssert(
"ArrayPool<T>::release", __FILE__, __LINE__);
1023 ErrorReporter::handleAssert(
"ArrayPool<T>::release", __FILE__, __LINE__);
1027 #define DUMP(a,b) do { printf("%s c.m_first_free: %u c.m_free_cnt: %u %s", a, c.m_first_free, c.m_free_cnt, b); fflush(stdout); } while(0)
1032 #ifdef ARRAY_CHUNK_GUARD
1039 assert(chunk ==
true);
1042 Uint32 ff = firstFree;
1046 sum += theArray[ff].chunkSize;
1047 Uint32 last = theArray[ff].lastChunk;
1048 assert(theArray[last].nextPool == theArray[ff].nextChunk);
1049 if (theAllocatedBitmask)
1055 tmp = theArray[tmp].nextPool;
1060 ff = theArray[ff].nextChunk;
1062 assert(sum == noOfFree);
1072 assert(chunk ==
true);
1075 #ifdef ARRAY_CHUNK_GUARD
1081 Uint32 ff = firstFree;
1083 ptr.p = theArray + ff;
1091 ndbout_c(
"seizeChunk(%u) ff: %u tmp: %d chunkSize: %u lastChunk: %u nextChunk: %u",
1093 theArray[ff].chunkSize,
1094 theArray[ff].lastChunk,
1095 theArray[ff].nextChunk);
1097 tmp -= theArray[ff].chunkSize;
1098 prev = theArray[ff].lastChunk;
1099 assert(theArray[ff].nextChunk == theArray[prev].nextPool);
1100 ff = theArray[ff].nextChunk;
1101 }
while (tmp > 0 && ff != RNIL);
1104 decNoFree(save - tmp);
1106 theArray[prev].nextPool = RNIL;
1109 if (theAllocatedBitmask)
1111 Uint32 tmpI = ptr.i;
1112 for(Uint32 i = 0; i<cnt; i++){
1117 ErrorReporter::handleAssert(
"ArrayPool<T>::seizeChunk",
1118 __FILE__, __LINE__);
1122 tmpI = theArray[tmpI].nextPool;
1127 #ifdef ARRAY_CHUNK_GUARD
1144 assert(chunk ==
true);
1147 #ifdef ARRAY_CHUNK_GUARD
1151 Uint32 ff = firstFree;
1153 theArray[first].nextChunk = ff;
1154 theArray[last].nextPool = ff;
1157 assert(theArray[first].chunkSize == cnt);
1158 assert(theArray[first].lastChunk == last);
1161 if (theAllocatedBitmask)
1164 for(Uint32 i = 0; i<cnt; i++){
1171 ErrorReporter::handleAssert(
"ArrayPool<T>::releaseList",
1172 __FILE__, __LINE__);
1175 tmp = theArray[tmp].nextPool;
1180 #ifdef ARRAY_CHUNK_GUARD
1191 DUMP(
"seize",
"-> ");
1193 Uint32 ff = c.m_first_free;
1196 c.m_first_free = theArray[ff].nextPool;
1199 p.p = theArray + ff;
1200 DUMP(
"LOCAL ",
"\n");
1204 Uint32 tmp = c.m_alloc_cnt;
1206 bool ret = seizeChunk(tmp, p);
1211 c.m_first_free = theArray[p.i].nextPool;
1212 c.m_free_cnt = tmp - 1;
1213 DUMP(
"LOCKED",
"\n");
1234 p.p->nextPool = c.m_first_free;
1235 c.m_first_free = p.i;
1238 if (c.m_free_cnt > 2 * c.m_max_free_cnt)
1240 releaseChunk(l, c, c.m_alloc_cnt);
1248 Uint32
n, Uint32 first, Uint32 last)
1250 theArray[last].nextPool = c.m_first_free;
1251 c.m_first_free = first;
1254 if (c.m_free_cnt > 2 * c.m_max_free_cnt)
1256 releaseChunk(l, c, c.m_alloc_cnt);
1265 DUMP(
"releaseListImpl",
"-> ");
1266 Uint32 ff = c.m_first_free;
1270 for (i = 0; i < n && curr != RNIL; i++)
1273 curr = theArray[curr].nextPool;
1275 c.m_first_free = curr;
1280 theArray[ff].chunkSize =
i;
1281 theArray[ff].lastChunk = prev;
1284 releaseChunk(i, ff, prev);
1298 const T * getConstPtrForce(Uint32 i)
const;
1308 if(likely(i < this->
size)){
1309 ptr.p = &this->theArray[
i];
1311 ErrorReporter::handleAssert(
"UnsafeArrayPool<T>::getPtr",
1312 __FILE__, __LINE__);
1321 if(likely(i < this->
size)){
1322 ptr.p = &this->theArray[
i];
1324 ErrorReporter::handleAssert(
"UnsafeArrayPool<T>::getPtr",
1325 __FILE__, __LINE__);
1333 if(likely(i < this->
size)){
1334 return &this->theArray[
i];
1336 ErrorReporter::handleAssert(
"UnsafeArrayPool<T>::getPtr",
1337 __FILE__, __LINE__);
1346 if(likely(i < this->
size)){
1347 return &this->theArray[
i];
1349 ErrorReporter::handleAssert(
"UnsafeArrayPool<T>::getPtr",
1350 __FILE__, __LINE__);
1360 if(likely(i < this->
size)){
1361 ptr.p = &this->theArray[
i];
1364 ErrorReporter::handleAssert(
"UnsafeArrayPool<T>::getPtr",
1365 __FILE__, __LINE__);
1374 if(likely(i < this->
size)){
1375 ptr.p = &this->theArray[
i];
1378 ErrorReporter::handleAssert(
"UnsafeArrayPool<T>::getPtr",
1379 __FILE__, __LINE__);
1401 bool findId(Uint32)
const;
1410 m_mutex_owner =
false;
1412 m_mutex = NdbMutex_Create();
1413 assert(m_mutex != 0);
1414 m_mutex_owner =
true;
1423 NdbMutex_Destroy(m_mutex);
1431 return NdbMutex_Lock(m_mutex);
1439 return NdbMutex_Unlock(m_mutex);