MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ArrayPool.hpp
1 /*
2  Copyright (C) 2003-2006, 2008 MySQL AB, 2008-2010 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #ifndef ARRAY_POOL_HPP
20 #define ARRAY_POOL_HPP
21 
22 #include <ndb_global.h>
23 #include "ndbd_malloc.hpp"
24 
25 #include <pc.hpp>
26 #include "Pool.hpp"
27 #include <ErrorReporter.hpp>
28 #include <NdbMem.h>
29 #include <Bitmask.hpp>
30 #include <mgmapi.h>
31 
32 #include <NdbMutex.h>
33 
34 template <class T> class Array;
35 
36 //#define ARRAY_CHUNK_GUARD
37 
42 template <class T>
43 class ArrayPool {
44 public:
45  ArrayPool();
46  ~ArrayPool();
47 
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; }
57 
58  inline Uint32 getNoOfFree() const {
59  return noOfFree;
60  }
61 
62  inline Uint32 getSize() const {
63  return size;
64  }
65 
66  inline Uint32 getUsed() const {
67  return size - noOfFree;
68  }
69 
70  inline Uint32 getUsedHi() const {
71  return size - noOfFreeMin;
72  }
73 
74  inline void updateFreeMin(void) {
75  if (noOfFree < noOfFreeMin)
76  noOfFreeMin = noOfFree;
77  }
78 
79  inline void decNoFree(void) {
80  assert(noOfFree > 0);
81  noOfFree--;
82  updateFreeMin();
83  }
84 
85  inline void decNoFree(Uint32 cnt) {
86  assert(noOfFree >= cnt);
87  noOfFree -= cnt;
88  updateFreeMin();
89  }
90 
91  inline Uint32 getEntrySize() const {
92  return sizeof(T);
93  }
94 
98  void getPtr(Ptr<T> &);
99  void getPtr(ConstPtr<T> &) const;
100  void getPtr(Ptr<T> &, bool CrashOnBoundaryError);
101  void getPtr(ConstPtr<T> &, bool CrashOnBoundaryError) const;
102 
106  T * getPtr(Uint32 i);
107  const T * getConstPtr(Uint32 i) const;
108  T * getPtr(Uint32 i, bool CrashOnBoundaryError);
109  const T * getConstPtr(Uint32 i, bool CrashOnBoundaryError) const;
110 
114  void getPtr(Ptr<T> &, Uint32 i);
115  void getPtr(ConstPtr<T> &, Uint32 i) const;
116  void getPtr(Ptr<T> &, Uint32 i, bool CrashOnBoundaryError);
117  void getPtr(ConstPtr<T> &, Uint32 i, bool CrashOnBoundaryError) const;
118 
124  bool seize(Ptr<T> &);
125 
129  bool seizeId(Ptr<T> &, Uint32 i);
130 
134  bool findId(Uint32 i) const;
135 
139  void release(Uint32 i);
140 
144  void release(Ptr<T> &);
145 
146 #ifdef ARRAY_GUARD
147 
155  bool isSeized(Uint32 i) const {
156  if (i>=size) return false;
157  return BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i);
158  }
159 #endif
160 
166  struct Cache
167  {
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; }
169  Uint32 m_first_free;
170  Uint32 m_free_cnt;
171  Uint32 m_alloc_cnt;
172  Uint32 m_max_free_cnt;
173  };
174 
175  struct LockFun
176  {
177  void (* lock)(void);
178  void (* unlock)(void);
179  };
180 
181  bool seize(LockFun, Cache&, Ptr<T> &);
182  void release(LockFun, Cache&, Uint32 i);
183  void release(LockFun, Cache&, Ptr<T> &);
184  void releaseList(LockFun, Cache&, Uint32 n, Uint32 first, Uint32 last);
185 
186  void setChunkSize(Uint32 sz);
187 #ifdef ARRAY_CHUNK_GUARD
188  void checkChunks();
189 #endif
190 
191 protected:
192  void releaseChunk(LockFun, Cache&, Uint32 n);
193 
194  bool seizeChunk(Uint32 & n, Ptr<T> &);
195  void releaseChunk(Uint32 n, Uint32 first, Uint32 last);
196 
197 protected:
198  friend class Array<T>;
199 
204  Uint32 seizeN(Uint32 n);
205 
210  void releaseN(Uint32 base, Uint32 n);
211 
212 public:
219  void releaseList(Uint32 n, Uint32 first, Uint32 last);
220  //private:
221 
222 #if 0
223  Uint32 getNoOfFree2() const {
224  Uint32 c2 = size;
225  for(Uint32 i = 0; i<((size + 31)>> 5); i++){
226  Uint32 w = theAllocatedBitmask[i];
227  for(Uint32 j = 0; j<32; j++){
228  if((w & 1) == 1){
229  c2--;
230  }
231  w >>= 1;
232  }
233  }
234  return c2;
235  }
236 
237  Uint32 getNoOfFree3() const {
238  Uint32 c = 0;
239  Ptr<T> p;
240  p.i = firstFree;
241  while(p.i != RNIL){
242  c++;
243  p.p = &theArray[p.i];
244  p.i = p.p->next;
245  }
246  return c;
247  }
248 #endif
249 
250 protected:
251  Uint32 firstFree;
252  Uint32 size;
253  Uint32 noOfFree;
254  Uint32 noOfFreeMin;
255  T * theArray;
256  void * alloc_ptr;
257 #ifdef ARRAY_GUARD
258  Uint32 bitmaskSz;
259  Uint32 *theAllocatedBitmask;
260  bool chunk;
261 #endif
262 };
263 
264 template <class T>
265 inline
267  firstFree = RNIL;
268  size = 0;
269  noOfFree = 0;
270  noOfFreeMin = 0;
271  theArray = 0;
272  alloc_ptr = 0;
273 #ifdef ARRAY_GUARD
274  theAllocatedBitmask = 0;
275  chunk = false;
276 #endif
277 }
278 
279 template <class T>
280 inline
282  if(theArray != 0){
283  ndbd_free(alloc_ptr, size * sizeof(T));
284  theArray = 0;
285  alloc_ptr = 0;
286 #ifdef ARRAY_GUARD
287  if (theAllocatedBitmask)
288  delete []theAllocatedBitmask;
289  theAllocatedBitmask = 0;
290 #endif
291  }
292 }
293 
299 template <class T>
300 inline
301 bool
302 ArrayPool<T>::setSize(Uint32 noOfElements,
303  bool align, bool exit_on_error, bool guard, Uint32 paramId){
304  if(size == 0){
305  if(noOfElements == 0)
306  return true;
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;
311 
312  if(align)
313  {
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);
318  if (mod)
319  {
320  p += sizeof(T) - mod;
321  }
322  theArray = (T *)p;
323  }
324  else if((Uint64)req_size == real_size && req_size > 0)
325  theArray = (T *)(alloc_ptr = ndbd_malloc(req_size));
326 
327  if(theArray == 0)
328  {
329  char errmsg[255] = "ArrayPool<T>::setSize malloc failed";
330  struct ndb_mgm_param_info param_info;
331  size_t tsize = sizeof(ndb_mgm_param_info);
332  if (!exit_on_error)
333  return false;
334 
335  if(0 != paramId && 0 == ndb_mgm_get_db_parameter_info(paramId, &param_info, &tsize)) {
336  BaseString::snprintf(errmsg, sizeof(errmsg),
337  "Malloc memory for %s failed", param_info.m_name);
338  }
339 
340  ErrorReporter::handleAssert(errmsg,
341  __FILE__, __LINE__, NDBD_EXIT_MEMALLOC);
342  return false; // not reached
343  }
344  size = noOfElements;
345  noOfFree = noOfElements;
346  noOfFreeMin = noOfElements;
347 
351  T * t = &theArray[0];
352  for(Uint32 i = 0; i<size; i++){
353  t->nextPool = (i + 1);
354  t++;
355  }
356  theArray[size-1].nextPool = RNIL;
357  firstFree = 0;
358 
359 #ifdef ARRAY_GUARD
360  if (guard)
361  {
362  bitmaskSz = (noOfElements + 31) >> 5;
363  theAllocatedBitmask = new Uint32[bitmaskSz];
364  BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask);
365  }
366 #endif
367 
368  return true;
369  }
370  if (!exit_on_error)
371  return false;
372 
373  ErrorReporter::handleAssert("ArrayPool<T>::setSize called twice", __FILE__, __LINE__);
374  return false; // not reached
375 }
376 
377 template <class T>
378 inline
379 void
381 {
382  Uint32 i;
383  for (i = 0; i + sz < size; i += sz)
384  {
385  theArray[i].chunkSize = sz;
386  theArray[i].lastChunk = i + sz - 1;
387  theArray[i].nextChunk = i + sz;
388  }
389 
390  theArray[i].chunkSize = size - i;
391  theArray[i].lastChunk = size - 1;
392  theArray[i].nextChunk = RNIL;
393 
394 #ifdef ARRAY_GUARD
395  chunk = true;
396 #endif
397 
398 #ifdef ARRAY_CHUNK_GUARD
399  checkChunks();
400 #endif
401 }
402 
403 template <class T>
404 inline
405 bool
406 ArrayPool<T>::set(T* ptr, Uint32 cnt, bool align){
407  if (size == 0)
408  {
409  alloc_ptr = ptr;
410  if(align)
411  {
412  UintPtr p = (UintPtr)alloc_ptr;
413  UintPtr mod = p % sizeof(T);
414  if (mod)
415  {
416  p += sizeof(T) - mod;
417  cnt --;
418  }
419  theArray = (T *)p;
420  }
421  else
422  {
423  theArray = (T *)alloc_ptr;
424  }
425 
426  size = cnt;
427  noOfFree = 0;
428  noOfFreeMin = 0;
429  return true;
430  }
431  ErrorReporter::handleAssert("ArrayPool<T>::set called twice",
432  __FILE__, __LINE__);
433  return false; // not reached
434 }
435 
436 template <class T>
437 inline
438 void
440  Uint32 i = ptr.i;
441  if(likely (i < size)){
442  ptr.p = &theArray[i];
443 #ifdef ARRAY_GUARD
444  if (theAllocatedBitmask)
445  {
446  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
447  return;
451  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
452  }
453 #endif
454  } else {
455  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
456  }
457 }
458 
459 template <class T>
460 inline
461 void
462 ArrayPool<T>::getPtr(ConstPtr<T> & ptr) const {
463  Uint32 i = ptr.i;
464  if(likely(i < size)){
465  ptr.p = &theArray[i];
466 #ifdef ARRAY_GUARD
467  if (theAllocatedBitmask)
468  {
469  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
470  return;
474  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
475  }
476 #endif
477  } else {
478  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
479  }
480 }
481 
482 template <class T>
483 inline
484 void
485 ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i){
486  ptr.i = i;
487  if(likely(i < size)){
488  ptr.p = &theArray[i];
489 #ifdef ARRAY_GUARD
490  if (theAllocatedBitmask)
491  {
492  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
493  return;
497  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
498  }
499 #endif
500  } else {
501  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
502  }
503 }
504 
505 template <class T>
506 inline
507 void
508 ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i) const {
509  ptr.i = i;
510  if(likely(i < size)){
511  ptr.p = &theArray[i];
512 #ifdef ARRAY_GUARD
513  if (theAllocatedBitmask)
514  {
515  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
516  return;
520  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
521  }
522 #endif
523  } else {
524  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
525  }
526 }
527 
528 template <class T>
529 inline
530 T *
532  if(likely(i < size)){
533 #ifdef ARRAY_GUARD
534  if (theAllocatedBitmask)
535  {
536  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
537  return &theArray[i];
541  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
542  return 0;
543  }
544 #endif
545  return &theArray[i];
546  } else {
547  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
548  return 0;
549  }
550 }
551 
552 template <class T>
553 inline
554 const T *
555 ArrayPool<T>::getConstPtr(Uint32 i) const {
556  if(likely(i < size)){
557 #ifdef ARRAY_GUARD
558  if (theAllocatedBitmask)
559  {
560  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
561  return &theArray[i];
565  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
566  return 0;
567  }
568 #endif
569  return &theArray[i];
570  } else {
571  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
572  return 0;
573  }
574 }
575 
576 template <class T>
577 inline
578 void
579 ArrayPool<T>::getPtr(Ptr<T> & ptr, bool CrashOnBoundaryError){
580  Uint32 i = ptr.i;
581  if(likely(i < size)){
582  ptr.p = &theArray[i];
583 #ifdef ARRAY_GUARD
584  if (theAllocatedBitmask)
585  {
586  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
587  return;
591  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
592  }
593 #endif
594  } else {
595  ptr.i = RNIL;
596  }
597 }
598 
599 template <class T>
600 inline
601 void
602 ArrayPool<T>::getPtr(ConstPtr<T> & ptr, bool CrashOnBoundaryError) const {
603  Uint32 i = ptr.i;
604  if(likely(i < size)){
605  ptr.p = &theArray[i];
606 #ifdef ARRAY_GUARD
607  if (theAllocatedBitmask)
608  {
609  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
610  return;
614  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
615  }
616 #endif
617  } else {
618  ptr.i = RNIL;
619  }
620 }
621 
622 template <class T>
623 inline
624 void
625 ArrayPool<T>::getPtr(Ptr<T> & ptr, Uint32 i, bool CrashOnBoundaryError){
626  ptr.i = i;
627  if(likely(i < size)){
628  ptr.p = &theArray[i];
629 #ifdef ARRAY_GUARD
630  if (theAllocatedBitmask)
631  {
632  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
633  return;
637  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
638  }
639 #endif
640  } else {
641  ptr.i = RNIL;
642  }
643 }
644 
645 template <class T>
646 inline
647 void
648 ArrayPool<T>::getPtr(ConstPtr<T> & ptr, Uint32 i,
649  bool CrashOnBoundaryError) const {
650  ptr.i = i;
651  if(likely(i < size)){
652  ptr.p = &theArray[i];
653 #ifdef ARRAY_GUARD
654  if (theAllocatedBitmask)
655  {
656  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
657  return;
661  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
662  }
663 #endif
664  } else {
665  ptr.i = RNIL;
666  }
667 }
668 
669 template <class T>
670 inline
671 T *
672 ArrayPool<T>::getPtr(Uint32 i, bool CrashOnBoundaryError){
673  if(likely(i < size)){
674 #ifdef ARRAY_GUARD
675  if (theAllocatedBitmask)
676  {
677  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
678  return &theArray[i];
682  ErrorReporter::handleAssert("ArrayPool<T>::getPtr", __FILE__, __LINE__);
683  return 0;
684  }
685 #endif
686  return &theArray[i];
687  } else {
688  return 0;
689  }
690 }
691 
692 template <class T>
693 inline
694 const T *
695 ArrayPool<T>::getConstPtr(Uint32 i, bool CrashOnBoundaryError) const {
696  if(likely(i < size)){
697 #ifdef ARRAY_GUARD
698  if (theAllocatedBitmask)
699  {
700  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i))
701  return &theArray[i];
705  ErrorReporter::handleAssert("ArrayPool<T>::getConstPtr", __FILE__,__LINE__);
706  return 0;
707  }
708 #endif
709  return &theArray[i];
710  } else {
711  return 0;
712  }
713 }
714 
720 template <class T>
721 inline
722 bool
724 #ifdef ARRAY_GUARD
725  assert(chunk == false);
726 #endif
727 
728  Uint32 ff = firstFree;
729  if(ff != RNIL){
730  firstFree = theArray[ff].nextPool;
731 
732  ptr.i = ff;
733  ptr.p = &theArray[ff];
734 #ifdef ARRAY_GUARD
735  if (theAllocatedBitmask)
736  {
737  if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){
738  BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff);
739  decNoFree();
740  return true;
741  } else {
745  ErrorReporter::handleAssert("ArrayPool<T>::seize", __FILE__, __LINE__);
746  return false;
747  }
748  }
749 #endif
750  decNoFree();
751  return true;
752  }
753  ptr.i = RNIL;
754  ptr.p = NULL;
755  return false;
756 }
757 
758 template <class T>
759 inline
760 bool
761 ArrayPool<T>::seizeId(Ptr<T> & ptr, Uint32 i){
762 #ifdef ARRAY_GUARD
763  assert(chunk == false);
764 #endif
765 
766  Uint32 ff = firstFree;
767  Uint32 prev = RNIL;
768  while(ff != i && ff != RNIL){
769  prev = ff;
770  ff = theArray[ff].nextPool;
771  }
772 
773  if(ff != RNIL){
774  if(prev == RNIL)
775  firstFree = theArray[ff].nextPool;
776  else
777  theArray[prev].nextPool = theArray[ff].nextPool;
778 
779  ptr.i = ff;
780  ptr.p = &theArray[ff];
781 #ifdef ARRAY_GUARD
782  if (theAllocatedBitmask)
783  {
784  if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, ff)){
785  BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, ff);
786  decNoFree();
787  return true;
788  } else {
792  ErrorReporter::handleAssert("ArrayPool<T>::seizeId", __FILE__, __LINE__);
793  return false;
794  }
795  }
796 #endif
797  decNoFree();
798  return true;
799  }
800  ptr.i = RNIL;
801  ptr.p = NULL;
802  return false;
803 }
804 
805 template <class T>
806 inline
807 bool
808 ArrayPool<T>::findId(Uint32 i) const {
809  if (i >= size)
810  return false;
811  Uint32 ff = firstFree;
812  while(ff != i && ff != RNIL){
813  ff = theArray[ff].nextPool;
814  }
815  return (ff == RNIL);
816 }
817 
818 template<class T>
819 Uint32
821 #ifdef ARRAY_GUARD
822  assert(chunk == false);
823 #endif
824 
825  Uint32 curr = firstFree;
826  Uint32 prev = RNIL;
827  Uint32 sz = 0;
828  while(sz < n && curr != RNIL){
829  if(theArray[curr].nextPool == (curr + 1)){
830  sz++;
831  } else {
832  sz = 0;
833  prev = curr;
834  }
835  curr = theArray[curr].nextPool;
836  }
837  if(sz != n){
838  return RNIL;
839  }
840  const Uint32 base = curr - n;
841  if(base == firstFree){
842  firstFree = curr;
843  } else {
844  theArray[prev].nextPool = curr;
845  }
846 
847  decNoFree(n);
848 #ifdef ARRAY_GUARD
849  if (theAllocatedBitmask)
850  {
851  for(Uint32 j = base; j<curr; j++){
852  if(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, j)){
853  BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, j);
854  } else {
858  ErrorReporter::handleAssert("ArrayPool<T>::seize", __FILE__, __LINE__);
859  return RNIL;
860  }
861  }
862  }
863 #endif
864  return base;
865 }
866 
867 template<class T>
868 inline
869 void
870 ArrayPool<T>::releaseN(Uint32 base, Uint32 n){
871 #ifdef ARRAY_GUARD
872  assert(chunk == false);
873 #endif
874 
875  Uint32 curr = firstFree;
876  Uint32 prev = RNIL;
877  while(curr < base){
878  prev = curr;
879  curr = theArray[curr].nextPool;
880  }
881  if(curr == firstFree){
882  firstFree = base;
883  } else {
884  theArray[prev].nextPool = base;
885  }
886  const Uint32 end = base + n;
887  for(Uint32 i = base; i<end; i++){
888 #ifdef ARRAY_GUARD
889  if (theAllocatedBitmask)
890  {
891  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
892  BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
893  } else {
897  ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
898  return;
899  }
900  }
901 #endif
902  theArray[i].nextPool = i + 1;
903  }
904  theArray[end-1].nextPool = curr;
905  noOfFree += n;
906 }
907 
908 template<class T>
909 inline
910 void
911 ArrayPool<T>::releaseList(Uint32 n, Uint32 first, Uint32 last){
912 
913 #ifdef ARRAY_GUARD
914  assert(chunk == false);
915 #endif
916 
917  assert( n != 0 );
918 
919  if(first < size && last < size){
920  Uint32 ff = firstFree;
921  firstFree = first;
922  theArray[last].nextPool = ff;
923  noOfFree += n;
924 
925 #ifdef ARRAY_GUARD
926  if (theAllocatedBitmask)
927  {
928  Uint32 tmp = first;
929  for(Uint32 i = 0; i<n; i++){
930  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp)){
931  BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, tmp);
932  } else {
936  ErrorReporter::handleAssert("ArrayPool<T>::releaseList",
937  __FILE__, __LINE__);
938  return;
939  }
940  tmp = theArray[tmp].nextPool;
941  }
942  }
943 #endif
944  return;
945  }
946  ErrorReporter::handleAssert("ArrayPool<T>::releaseList", __FILE__, __LINE__);
947 }
948 
952 template <class T>
953 inline
954 void
956 
957 #ifdef ARRAY_GUARD
958  assert(chunk == false);
959 #endif
960 
961  const Uint32 i = _i;
962  if(likely(i < size)){
963  Uint32 ff = firstFree;
964  theArray[i].nextPool = ff;
965  firstFree = i;
966 
967 #ifdef ARRAY_GUARD
968  if (theAllocatedBitmask)
969  {
970  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
971  BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
972  noOfFree++;
973  return;
974  }
978  ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
979  }
980 #endif
981  noOfFree++;
982  return;
983  }
984  ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
985 }
986 
990 template <class T>
991 inline
992 void
994 
995 #ifdef ARRAY_GUARD
996  assert(chunk == false);
997 #endif
998 
999  Uint32 i = ptr.i;
1000  if(likely(i < size)){
1001  Uint32 ff = firstFree;
1002  theArray[i].nextPool = ff;
1003  firstFree = i;
1004 
1005 #ifdef ARRAY_GUARD
1006  if (theAllocatedBitmask)
1007  {
1008  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, i)){
1009  BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, i);
1010  //assert(noOfFree() == noOfFree2());
1011  noOfFree++;
1012  return;
1013  }
1017  ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
1018  }
1019 #endif
1020  noOfFree++;
1021  return;
1022  }
1023  ErrorReporter::handleAssert("ArrayPool<T>::release", __FILE__, __LINE__);
1024 }
1025 
1026 #if 0
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)
1028 #else
1029 #define DUMP(a,b)
1030 #endif
1031 
1032 #ifdef ARRAY_CHUNK_GUARD
1033 template <class T>
1034 inline
1035 void
1037 {
1038 #ifdef ARRAY_GUARD
1039  assert(chunk == true);
1040 #endif
1041 
1042  Uint32 ff = firstFree;
1043  Uint32 sum = 0;
1044  while (ff != RNIL)
1045  {
1046  sum += theArray[ff].chunkSize;
1047  Uint32 last = theArray[ff].lastChunk;
1048  assert(theArray[last].nextPool == theArray[ff].nextChunk);
1049  if (theAllocatedBitmask)
1050  {
1051  Uint32 tmp = ff;
1052  while(tmp != last)
1053  {
1054  assert(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp));
1055  tmp = theArray[tmp].nextPool;
1056  }
1057  assert(!BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp));
1058  }
1059 
1060  ff = theArray[ff].nextChunk;
1061  }
1062  assert(sum == noOfFree);
1063 }
1064 #endif
1065 
1066 template <class T>
1067 inline
1068 bool
1069 ArrayPool<T>::seizeChunk(Uint32 & cnt, Ptr<T> & ptr)
1070 {
1071 #ifdef ARRAY_GUARD
1072  assert(chunk == true);
1073 #endif
1074 
1075 #ifdef ARRAY_CHUNK_GUARD
1076  checkChunks();
1077 #endif
1078 
1079  Uint32 save = cnt;
1080  int tmp = save;
1081  Uint32 ff = firstFree;
1082  ptr.i = ff;
1083  ptr.p = theArray + ff;
1084 
1085  if (ff != RNIL)
1086  {
1087  Uint32 prev;
1088  do
1089  {
1090  if (0)
1091  ndbout_c("seizeChunk(%u) ff: %u tmp: %d chunkSize: %u lastChunk: %u nextChunk: %u",
1092  save, ff, tmp,
1093  theArray[ff].chunkSize,
1094  theArray[ff].lastChunk,
1095  theArray[ff].nextChunk);
1096 
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);
1102 
1103  cnt = (save - tmp);
1104  decNoFree(save - tmp);
1105  firstFree = ff;
1106  theArray[prev].nextPool = RNIL;
1107 
1108 #ifdef ARRAY_GUARD
1109  if (theAllocatedBitmask)
1110  {
1111  Uint32 tmpI = ptr.i;
1112  for(Uint32 i = 0; i<cnt; i++){
1113  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmpI)){
1117  ErrorReporter::handleAssert("ArrayPool<T>::seizeChunk",
1118  __FILE__, __LINE__);
1119  } else {
1120  BitmaskImpl::set(bitmaskSz, theAllocatedBitmask, tmpI);
1121  }
1122  tmpI = theArray[tmpI].nextPool;
1123  }
1124  }
1125 #endif
1126 
1127 #ifdef ARRAY_CHUNK_GUARD
1128  checkChunks();
1129 #endif
1130 
1131  return true;
1132  }
1133 
1134  ptr.p = NULL;
1135  return false;
1136 }
1137 
1138 template <class T>
1139 inline
1140 void
1141 ArrayPool<T>::releaseChunk(Uint32 cnt, Uint32 first, Uint32 last)
1142 {
1143 #ifdef ARRAY_GUARD
1144  assert(chunk == true);
1145 #endif
1146 
1147 #ifdef ARRAY_CHUNK_GUARD
1148  checkChunks();
1149 #endif
1150 
1151  Uint32 ff = firstFree;
1152  firstFree = first;
1153  theArray[first].nextChunk = ff;
1154  theArray[last].nextPool = ff;
1155  noOfFree += cnt;
1156 
1157  assert(theArray[first].chunkSize == cnt);
1158  assert(theArray[first].lastChunk == last);
1159 
1160 #ifdef ARRAY_GUARD
1161  if (theAllocatedBitmask)
1162  {
1163  Uint32 tmp = first;
1164  for(Uint32 i = 0; i<cnt; i++){
1165  if(BitmaskImpl::get(bitmaskSz, theAllocatedBitmask, tmp)){
1166  BitmaskImpl::clear(bitmaskSz, theAllocatedBitmask, tmp);
1167  } else {
1171  ErrorReporter::handleAssert("ArrayPool<T>::releaseList",
1172  __FILE__, __LINE__);
1173  return;
1174  }
1175  tmp = theArray[tmp].nextPool;
1176  }
1177  }
1178 #endif
1179 
1180 #ifdef ARRAY_CHUNK_GUARD
1181  checkChunks();
1182 #endif
1183 }
1184 
1185 
1186 template <class T>
1187 inline
1188 bool
1189 ArrayPool<T>::seize(LockFun l, Cache& c, Ptr<T> & p)
1190 {
1191  DUMP("seize", "-> ");
1192 
1193  Uint32 ff = c.m_first_free;
1194  if (ff != RNIL)
1195  {
1196  c.m_first_free = theArray[ff].nextPool;
1197  c.m_free_cnt--;
1198  p.i = ff;
1199  p.p = theArray + ff;
1200  DUMP("LOCAL ", "\n");
1201  return true;
1202  }
1203 
1204  Uint32 tmp = c.m_alloc_cnt;
1205  l.lock();
1206  bool ret = seizeChunk(tmp, p);
1207  l.unlock();
1208 
1209  if (ret)
1210  {
1211  c.m_first_free = theArray[p.i].nextPool;
1212  c.m_free_cnt = tmp - 1;
1213  DUMP("LOCKED", "\n");
1214  return true;
1215  }
1216  return false;
1217 }
1218 
1219 template <class T>
1220 inline
1221 void
1222 ArrayPool<T>::release(LockFun l, Cache& c, Uint32 i)
1223 {
1224  Ptr<T> tmp;
1225  getPtr(tmp, i);
1226  release(l, c, tmp);
1227 }
1228 
1229 template <class T>
1230 inline
1231 void
1232 ArrayPool<T>::release(LockFun l, Cache& c, Ptr<T> & p)
1233 {
1234  p.p->nextPool = c.m_first_free;
1235  c.m_first_free = p.i;
1236  c.m_free_cnt ++;
1237 
1238  if (c.m_free_cnt > 2 * c.m_max_free_cnt)
1239  {
1240  releaseChunk(l, c, c.m_alloc_cnt);
1241  }
1242 }
1243 
1244 template <class T>
1245 inline
1246 void
1247 ArrayPool<T>::releaseList(LockFun l, Cache& c,
1248  Uint32 n, Uint32 first, Uint32 last)
1249 {
1250  theArray[last].nextPool = c.m_first_free;
1251  c.m_first_free = first;
1252  c.m_free_cnt += n;
1253 
1254  if (c.m_free_cnt > 2 * c.m_max_free_cnt)
1255  {
1256  releaseChunk(l, c, c.m_alloc_cnt);
1257  }
1258 }
1259 
1260 template <class T>
1261 inline
1262 void
1263 ArrayPool<T>::releaseChunk(LockFun l, Cache& c, Uint32 n)
1264 {
1265  DUMP("releaseListImpl", "-> ");
1266  Uint32 ff = c.m_first_free;
1267  Uint32 prev = ff;
1268  Uint32 curr = ff;
1269  Uint32 i;
1270  for (i = 0; i < n && curr != RNIL; i++)
1271  {
1272  prev = curr;
1273  curr = theArray[curr].nextPool;
1274  }
1275  c.m_first_free = curr;
1276  c.m_free_cnt -= i;
1277 
1278  DUMP("", "\n");
1279 
1280  theArray[ff].chunkSize = i;
1281  theArray[ff].lastChunk = prev;
1282 
1283  l.lock();
1284  releaseChunk(i, ff, prev);
1285  l.unlock();
1286 }
1287 
1288 template <class T>
1289 class UnsafeArrayPool : public ArrayPool<T> {
1290 public:
1295  void getPtrForce(Ptr<T> &);
1296  void getPtrForce(ConstPtr<T> &) const;
1297  T * getPtrForce(Uint32 i);
1298  const T * getConstPtrForce(Uint32 i) const;
1299  void getPtrForce(Ptr<T> &, Uint32 i);
1300  void getPtrForce(ConstPtr<T> &, Uint32 i) const;
1301 };
1302 
1303 template <class T>
1304 inline
1305 void
1307  Uint32 i = ptr.i;
1308  if(likely(i < this->size)){
1309  ptr.p = &this->theArray[i];
1310  } else {
1311  ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
1312  __FILE__, __LINE__);
1313  }
1314 }
1315 
1316 template <class T>
1317 inline
1318 void
1320  Uint32 i = ptr.i;
1321  if(likely(i < this->size)){
1322  ptr.p = &this->theArray[i];
1323  } else {
1324  ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
1325  __FILE__, __LINE__);
1326  }
1327 }
1328 
1329 template <class T>
1330 inline
1331 T *
1333  if(likely(i < this->size)){
1334  return &this->theArray[i];
1335  } else {
1336  ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
1337  __FILE__, __LINE__);
1338  return 0;
1339  }
1340 }
1341 
1342 template <class T>
1343 inline
1344 const T *
1345 UnsafeArrayPool<T>::getConstPtrForce(Uint32 i) const {
1346  if(likely(i < this->size)){
1347  return &this->theArray[i];
1348  } else {
1349  ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
1350  __FILE__, __LINE__);
1351  return 0;
1352  }
1353 }
1354 
1355 template <class T>
1356 inline
1357 void
1358 UnsafeArrayPool<T>::getPtrForce(Ptr<T> & ptr, Uint32 i){
1359  ptr.i = i;
1360  if(likely(i < this->size)){
1361  ptr.p = &this->theArray[i];
1362  return ;
1363  } else {
1364  ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
1365  __FILE__, __LINE__);
1366  }
1367 }
1368 
1369 template <class T>
1370 inline
1371 void
1372 UnsafeArrayPool<T>::getPtrForce(ConstPtr<T> & ptr, Uint32 i) const{
1373  ptr.i = i;
1374  if(likely(i < this->size)){
1375  ptr.p = &this->theArray[i];
1376  return ;
1377  } else {
1378  ErrorReporter::handleAssert("UnsafeArrayPool<T>::getPtr",
1379  __FILE__, __LINE__);
1380  }
1381 }
1382 
1383 // SafeArrayPool
1384 
1385 template <class T>
1386 class SafeArrayPool : public ArrayPool<T> {
1387 public:
1388  SafeArrayPool(NdbMutex* mutex = 0);
1389  ~SafeArrayPool();
1390  int lock();
1391  int unlock();
1392  bool seize(Ptr<T>&);
1393  void release(Uint32 i);
1394  void release(Ptr<T>&);
1395 
1396 private:
1397  NdbMutex* m_mutex;
1398  bool m_mutex_owner;
1399 
1400  bool seizeId(Ptr<T>&);
1401  bool findId(Uint32) const;
1402 };
1403 
1404 template <class T>
1405 inline
1406 SafeArrayPool<T>::SafeArrayPool(NdbMutex* mutex)
1407 {
1408  if (mutex != 0) {
1409  m_mutex = mutex;
1410  m_mutex_owner = false;
1411  } else {
1412  m_mutex = NdbMutex_Create();
1413  assert(m_mutex != 0);
1414  m_mutex_owner = true;
1415  }
1416 }
1417 
1418 template <class T>
1419 inline
1421 {
1422  if (m_mutex_owner)
1423  NdbMutex_Destroy(m_mutex);
1424 }
1425 
1426 template <class T>
1427 inline
1428 int
1430 {
1431  return NdbMutex_Lock(m_mutex);
1432 }
1433 
1434 template <class T>
1435 inline
1436 int
1438 {
1439  return NdbMutex_Unlock(m_mutex);
1440 }
1441 
1442 template <class T>
1443 inline
1444 bool
1446 {
1447  bool ok = false;
1448  if (lock() == 0) {
1449  ok = ArrayPool<T>::seize(ptr);
1450  unlock();
1451  }
1452  return ok;
1453 }
1454 
1455 template <class T>
1456 inline
1457 void
1459 {
1460  int ret = lock();
1461  assert(ret == 0);
1463  unlock();
1464 }
1465 
1466 template <class T>
1467 inline
1468 void
1470 {
1471  int ret = lock();
1472  assert(ret == 0);
1473  ArrayPool<T>::release(ptr);
1474  unlock();
1475 }
1476 
1477 #endif