]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/STEERBase/AliPoolN.cxx
declaring clusters as const prevents the [] operator from allocating memory
[u/mrichter/AliRoot.git] / STEER / STEERBase / AliPoolN.cxx
CommitLineData
e546b023 1#include "AliPoolN.h"
2#include "AliLog.h"
3#include <TMath.h>
4
5
6ClassImp(AliPoolN)
7
8//_______________________________________________
9AliPoolN& 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//_______________________________________________
27void AliPoolN::Clear(Option_t*)
28{
29 // reset
30 fNBooked = fFreeSlot = fNFreed = 0;
31 SetUniqueID(0);
32}
33
34//_______________________________________________
35int* 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//_______________________________________________
83void 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//_______________________________________________
92AliPoolN::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//_______________________________________________
100AliPoolN::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//_______________________________________________
108void 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//_______________________________________________
116Int_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//_______________________________________________
149void 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}