]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/STEERBase/AliPoolN.cxx
declaring clusters as const prevents the [] operator from allocating memory
[u/mrichter/AliRoot.git] / STEER / STEERBase / AliPoolN.cxx
1 #include "AliPoolN.h"
2 #include "AliLog.h"
3 #include <TMath.h>
4
5
6 ClassImp(AliPoolN)
7
8 //_______________________________________________
9 AliPoolN& AliPoolN::operator=(const AliPoolN& src)
10 {
11   // assign
12   if (this!=&src) {
13     if (fPool) delete[] fPool;
14     fSize = src.fSize;
15     fPool = new Int_t[fSize];
16     memcpy(fPool,src.fPool,sizeof(Int_t)*fSize);
17     fPtrSlot = src.fPtrSlot;
18     fFreeSlot = src.fFreeSlot;
19     fNBooked  = src.fNBooked;
20     fNFreed   = src.fNFreed;
21   }
22   return *this;
23 }
24
25
26 //_______________________________________________
27 void AliPoolN::Clear(Option_t*) 
28 {
29   // reset 
30   fNBooked = fFreeSlot = fNFreed = 0;
31   SetUniqueID(0);
32 }
33
34 //_______________________________________________
35 int* AliPoolN::BookSlots(void** addr, int n, int wsize)
36 {
37   // book n slots of size wsize (aligning to sizeof(int))
38   const int kIntW = sizeof(Int_t);
39   const int kDivW = TMath::Log2(sizeof(Int_t));
40   const int kPtrW = sizeof(void*);
41   const int kPtrIW = kPtrW/kIntW; // pointer length in int words
42   static int eCounter = 0;
43   //
44   if (n<1) return 0;
45   int nbtot = n*wsize; // total bytes to book (apart from addr)
46   if (nbtot%kIntW) nbtot = (((nbtot>>kDivW)+1)<<kDivW); // make sure it is in Int words (normally 4 bites)
47   int nw = kPtrIW + (nbtot>>kDivW); // number of int words to book (including space for pointer)
48   UInt_t newFreeSlot = fFreeSlot+nw;
49   //
50   if (UInt_t(fPtrSlot.GetSize())<=fNBooked) fPtrSlot.Set( 2*(fNBooked+10) );
51   int* ptrS = fPtrSlot.GetArray();
52   if (fSize<=newFreeSlot) {   // do we need to expand the array ?
53     //
54     int sizeN = int((newFreeSlot+10000)*1.5);
55     Int_t* oldArr = fPool;
56     fPool = new Int_t[sizeN];
57     if (fSize) memcpy(fPool,oldArr, fSize*sizeof(Int_t));
58     memset(&fPool[fSize],0,(sizeN-fSize)*sizeof(Int_t));
59     //
60     for (UInt_t i=0;i<fNBooked;i++) {       // fix old addresses
61       void* oldP  = (void*)&oldArr[ ptrS[i]+kPtrIW ];
62       void** slotP = (void**)&fPool[ ptrS[i] ];
63       void** ppp = (void**)slotP[0];
64       //      printf("1>>%d %p %p old:%p\n",i,ppp, ppp ? *ppp : 0,oldP);
65       if (!ppp || *ppp!=oldP) continue; // array was discarded      
66       *ppp = &fPool[ ptrS[i]+kPtrIW ];
67     }
68     fSize = sizeN;
69     delete[] oldArr;
70     AliInfo(Form("Expansion %d: Size:%d, Object Booked:%d, Freed:%d, Next Free Slot:%d\n",
71                  ++eCounter,fSize,fNBooked,fNFreed,fFreeSlot));
72   }
73   ptrS[fNBooked++] = fFreeSlot;
74   void** slotP = (void**)&fPool[ fFreeSlot ];
75   slotP[0] = addr;
76   SetUniqueID(fFreeSlot+kPtrIW);
77   fFreeSlot = newFreeSlot;
78   //
79   return &fPool[GetUniqueID()];
80 }
81
82 //_______________________________________________
83 void AliPoolN::PrintSummary(Option_t*) const
84 {
85   // print summary
86   printf("Pool: Num.Arrays: Size:%d, Object Booked:%d, Freed:%d, Next Free Slot:%d\n",
87          fSize,fNBooked,fNFreed,fFreeSlot);
88 }
89  
90
91 //_______________________________________________
92 AliPoolN::AliPoolN(Int_t nini) : 
93   fSize(nini>100 ? nini:10000),fPool(new Int_t[fSize]),fPtrSlot(fSize/10),fNBooked(0),
94   fNFreed(0),fFreeSlot(0) 
95 {
96   // c-tor
97 }
98
99 //_______________________________________________
100 AliPoolN::AliPoolN(const AliPoolN& src) : 
101   TObject(src), fSize(src.fSize),fPool(new Int_t[fSize]),fPtrSlot(src.fPtrSlot), 
102   fNBooked(src.fNBooked), fNFreed(src.fNFreed),fFreeSlot(src.fFreeSlot) 
103 {
104   // c-tor
105 }
106
107 //_______________________________________________
108 void AliPoolN::FreeSlot(void* adr) 
109 {
110   char** adrc = (char**)adr; 
111   if (!(*adrc)) return; //{ printf("ATTENTION: 0 pointer is freed\n"); return; }
112   *adrc = NULL; fNFreed++;
113 }
114
115 //_______________________________________________
116 Int_t AliPoolN::GetUsedSize()
117 {
118   // estimate which fraction of array is actually used
119   const int kIntW = sizeof(Int_t);
120   const int kPtrW = sizeof(void*);
121   const int kPtrIW = kPtrW/kIntW; // pointer length in int words
122   //
123   if (fFreeSlot<1) return 0.; // empty
124   int nFreeW=0, freeStart=-1,freeEnd=-1;
125   int* ptrS = fPtrSlot.GetArray();
126   //
127   for (UInt_t i=0;i<fNBooked;i++) {
128     void* arrP  = (void*)&fPool[ ptrS[i]+kPtrIW ]; // address of the booked array
129     void** slotP = (void**)&fPool[ ptrS[i] ];      // address of the external pointer to which this array was attached
130     void** ppp = (void**)slotP[0];
131     if (!ppp || *ppp!=arrP) { // the array was discarded
132       if (freeStart<0) {freeStart = ptrS[i]; freeEnd = -1;}
133     }
134     else if (freeStart!=-1) {
135       freeEnd = ptrS[i]; // end of free blocks
136       nFreeW += freeEnd-freeStart;
137       freeStart = -1;
138     }
139   }
140   if (freeStart!=-1 && freeEnd<0) { // last blocks were freed
141     freeEnd = fFreeSlot;
142     nFreeW += freeEnd-freeStart;
143   }
144   return fFreeSlot - nFreeW;
145   //
146 }
147
148 //_______________________________________________
149 void AliPoolN::Defragment()
150 {
151   // deframent the pool
152   const int kIntW = sizeof(Int_t);
153   const int kPtrW = sizeof(void*);
154   const int kPtrIW = kPtrW/kIntW; // pointer length in int words
155   //
156   if (fFreeSlot<1) return; // empty
157   int freeStart=-1,useStart=-1,useFirst=-1;
158   int* ptrS = fPtrSlot.GetArray();
159   int cnt = 0, shift = 0;
160   
161   //
162   for (UInt_t i=0;i<fNBooked;i++) {
163     void* arrP  = (void*)&fPool[ ptrS[i]+kPtrIW ]; // address of the booked array
164     void** slotP = (void**)&fPool[ ptrS[i] ];      // address of the external pointer to which this array was attached
165     void** ppp = (void**)slotP[0];
166     if (!ppp || *ppp!=arrP) { // the array was discarded
167       if (useStart!=-1) { // and it is also the end of the used block
168         if (freeStart!=-1) { // and there was a free block before
169           int moved = ptrS[i]-useStart;
170           shift = useStart-freeStart;
171           memmove(&fPool[freeStart], &fPool[useStart], kIntW*moved);
172           // update pointers for moved block
173           for (UInt_t j=useFirst;j<i;j++) { // used block covered these arrays
174             int slt = ptrS[cnt++] = ptrS[j]-shift; // updated index of the slot corresponding to array in the used block
175             slotP = (void**)&fPool[ slt ];
176             ppp = (void**)slotP[0];
177             *ppp = &fPool[ slt+kPtrIW ];           // assign external array address the new pointer on the begginning of the array
178           }
179           freeStart = ptrS[i]-shift; // mark beginning of the new free block
180           useStart = -1; // forget already treated used block 
181         }
182         else {
183           useStart = -1;       // forget this used block, it is already in defragmented part
184           freeStart = ptrS[i]; // no free block before, just mark beginning of new free block
185         }
186       }
187       else if (freeStart==-1) freeStart = ptrS[i]; // previous slot was not used: mark beginning of new free block
188     }
189     else { // the array is used
190       if (useStart==-1) { // and it is in the beginning of the used block
191         useStart = ptrS[i];
192         useFirst = i;   
193       }
194       if (freeStart==-1) cnt++; // no free block before, this array will not be moved
195     }
196   }
197   //
198   if (useStart!=-1 && freeStart!=-1) { // is there a last used block separated from defragmented part by empty block
199     int moved = fFreeSlot-useStart;
200     shift = useStart-freeStart;
201     memmove(&fPool[freeStart], &fPool[useStart], kIntW*moved);
202     // update pointers for moved block
203     for (UInt_t j=useFirst;j<fNBooked;j++) { // used block covered these arrays
204       int slt = ptrS[cnt++] = ptrS[j]-shift; // updated index of the slot corresponding to array in the used block
205       void** slotP = (void**)&fPool[ slt ];
206       void** ppp = (void**)slotP[0];       // address of the pointer to which the array was assigned
207       *ppp = &fPool[ slt+kPtrIW ];         // assign to it the new begginning of the array
208     }
209   }
210   fFreeSlot -= shift;
211   fNBooked = cnt;
212   fNFreed  = 0;
213   AliInfo(Form("Freed %d words",shift));
214   //
215 }