Remove minor warning
[u/mrichter/AliRoot.git] / CONTAINERS / AliMemArray.cxx
CommitLineData
08edbb90 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
88cb7938 16/* $Id$ */
70479d0e 17
08edbb90 18///////////////////////////////////////////////////////////////////////////////
19// //
20// AliMemArray //
21// (Pseudo)Container optimised for fast random access operator[ ].
22// Operator [] time doesn’t depend on the number of elements in container O(1) -
23// like in standard array or like in STL vector
24// To achieve maximally-fast indexing and iteration in one buffer mode
25// the vector maintains its storage as a single contiguous array of objects (one buffer mode)
26
27// When a vector runs out of pre-allocated storage, in order to maintain it
28// contiguous array it must allocate a whole new (larger) chunk of storage
29// elsewhere and copy the objects to the new storage.
30// void * AliMemArray::Unchecked1DAt(UInt_t i) const
31// return &(((char*)fCont)[fObjectSize*i]);
32
33// In multi buffer mode (like two dimensional array) when a vector runs out of
34// pre-allocated storage we don’t need to copy whole array only small buffer but operator [] is slower
35// void * AliMemArray::Unchecked2DAt(UInt_t i, UInt_t j) const
36// return &( ((char**)fCont)[i] [j*fObjectSize]);
37// void * AliMemArray::Unchecked2DAt(UInt_t i) const
38// return &( ((char**)fCont)[i/fBufferSize] [(i%fBufferSize)*fObjectSize]) ;
39
40
41//Begin_Html
42//<img src="../gif/AliMemArray.gif">
43//End_Html
44
45
46// Streamer CTORBuffer and DTORBuffer are virtual - should be implemented in derived
47// classes. For example AliObjectArray derived from AliMemArray is general array
48// for objects with defined AliClassInfo information.
49// //
50// //
51// Origin: Marian Ivanov, Uni. of Bratislava, ivanov@fmph.uniba.sk //
52///////////////////////////////////////////////////////////////////////////////
53
54
55
56#include "AliMemArray.h"
70479d0e 57#include "Riostream.h"
08edbb90 58#include "TMath.h"
59#include "TError.h"
60
61
62ClassImp(AliMemArray)
63
64
65AliMemArray::AliMemArray()
66{
67 //
68 //default constructor
69 //
70 fCont = 0;
71 fSize = 0;
72 fCapacity=0;
73 fObjectSize = 0;
74 fBufferSize = 0;
75}
76
77AliMemArray::AliMemArray(Int_t objectSize, Int_t buffersize)
78{
79 //
80 // AliMemArray constructor
81 fCont = 0;
82 fSize = 0;
83 fCapacity=0;
84 fObjectSize =objectSize;
85 fBufferSize =buffersize;
86}
87
88cb7938 88AliMemArray::AliMemArray(const AliMemArray & arr):
89 TObject(arr)
08edbb90 90{
91 //
92 //copy constructor
93 fCont = arr.fCont;
94 fSize = arr.fSize;
95 fCapacity = arr.fCapacity;
96 fObjectSize = arr.fObjectSize;
97 fBufferSize =arr.fBufferSize;
98
99 if (arr.fBufferSize==0) {
100 fCont = new char[fCapacity*fObjectSize];
101 CopyBuffer(fCont, arr.fCont, fSize);
102 }
103 else{
104 Int_t buffers = fCapacity/fBufferSize;
105 if (fCapacity%fBufferSize) buffers++;
106 void ** table = (void**) new char*[buffers];
107 for (Int_t i=0; i<buffers;i++){
108 table[i] = new char[fBufferSize*fObjectSize];
109 Int_t size = fSize - i*fBufferSize;
110 if (size > (Int_t)fBufferSize) size = fBufferSize;
111 if (size >0) CopyBuffer(table[i], ((void**)arr.fCont)[i],size);
112 }
113 fCont = (void*)table;
114 }
115}
116
117
118void AliMemArray::Swap( AliMemArray &arr)
119{
120 //swap contents of array
121 UInt_t size = arr.fSize;
122 arr.fSize = fSize;
123 fSize = size;
124 UInt_t capacity = arr.fCapacity;
125 arr.fCapacity = fCapacity;
126 fCapacity = capacity;
127 UInt_t objectSize = arr.fObjectSize;
128 arr.fObjectSize = fObjectSize;
129 fObjectSize = objectSize;
130 UInt_t bufferSize = arr.fBufferSize;
131 arr.fBufferSize = fBufferSize;
132 fBufferSize = bufferSize;
133 void * cont = arr.fCont;
134 arr.fCont = fCont;
135 fCont = cont;
136}
137
138void AliMemArray::CopyBuffer(void *dest, void *src, UInt_t size)
139{
140 //
141 //array placement copy constructor
142 memcpy(dest, src,size*fObjectSize);
143}
144
145AliMemArray::~AliMemArray()
146{
147 //
148 //default destructor
149 Delete();
150}
151
152
153void AliMemArray::SetObjectSize(UInt_t bufsize)
154{
155 //
156 //set memory size for one object - it can be changed only when the array is empty
157 if (fCont){
158 ::Error("AliMemArray::SetObjectSize", "forbidden to resize just allocated objects");
159 return;
160 };
161 fBufferSize=bufsize;
162}
163
164AliMemArray & AliMemArray::operator = (const AliMemArray &arr)
165{
166 //
167 //
168 AliMemArray tmparr(arr);
169 Swap(tmparr);
170 return *this;
171}
172
173void AliMemArray::SetBufferSize(UInt_t bufsize)
174{
175 //
176 //set buffer size - it can be changed only when the array is empty
177 if (fCont==0) {
178 fBufferSize = bufsize;
179 return;
180 }
181 if (fBufferSize == bufsize) return;
182
183 if (bufsize==0){
184 char *table = new char[fObjectSize*fCapacity];
185 char * p = table;
186 for (UInt_t i=0; i<fSize; i++,p+=fObjectSize)
187 memcpy(p, At(i), fObjectSize);
188 //delete [](char*)fCont;
189 Delete();
190 fCont = table;
191 fBufferSize = bufsize;
192 }
193 else{
194 Int_t buffers = fCapacity/bufsize;
195 if (fCapacity%bufsize) buffers++;
196 char ** table = new char*[buffers];
197 for (Int_t ibuf=0; ibuf<buffers;ibuf++){
198 table[ibuf] = new char[bufsize*fObjectSize];
199 Int_t size = fSize - ibuf*bufsize;
200 if (size > (Int_t)bufsize) size = bufsize;
201 if (size >0) for ( Int_t ip=0;ip<size;ip++)
202 memcpy(&table[ibuf][ip*fObjectSize], At(ibuf*bufsize+ip), fObjectSize);
203 }
204 // delete [](char**)fCont;
205 Delete();
206 fCont = (void*)table;
207 fBufferSize = bufsize;
208 }
209
210}
211
212
213
214void AliMemArray::Delete(Option_t *)
215{
216 //
217 //delete memory space occupied by the array -
218 //Use this routine when your objects allocate
219 //memory (e.g. objects inheriting from TNamed or containing TStrings
220 //allocate memory). If not you better use Clear() since if is faster.
221 if (fCont){
222 if (fBufferSize) {
223 Delete2D();
224 fSize = 0;
225 fCapacity = 0;
226 return;
227 }
228 DTORBuffer(Unchecked1DAt(0),fSize);
229 delete [] (char*)fCont;
230 fCont = 0;
231 fSize = 0;
232 fCapacity = 0;
233 }
234}
235
236void AliMemArray::Clear(Option_t *)
237{
238 //
239 //clear array -
240 // Only use this routine when your objects don't
241 // allocate memory since it will not call the object dtors.
242 if (fBufferSize){
243 Clear2D();
244 return;
245 }
246 if (fCont){
e36f9c7d 247 // memset(fCont, 0, fSize*fObjectSize);
248 //MI change - to have the same as in TClonesArray
08edbb90 249 fSize = 0;
250 }
251}
252
253void AliMemArray::Reserve(UInt_t n)
254{
255 //
256 //reserve arrays space
257 //
258 if (fObjectSize<=0) {
259 cout<<"Object length not defined\n";
260 return;
261 }
262 if (n==fCapacity) return;
263
264 if (fBufferSize>0) {
265 Reserve2D(n); //if 2D buffer
266 return;
267 }
268 //
269 if (fCapacity){
270 if (fSize>n) {
271 DTORBuffer(Unchecked1DAt(n),fSize-n);
272 memset(&((char*)fCont)[n*fObjectSize], 0, (fSize-n)*fObjectSize);
273 fSize =n;
274 }
275 fCont = (char*)TStorage::ReAlloc(fCont, n*fObjectSize,fCapacity*fObjectSize);
276 }
277 else fCont = new char[n*fObjectSize];
278
279 if (!fCont) fCapacity = 0;
280 else fCapacity = n;
281}
282
283
284void AliMemArray::Resize(UInt_t n)
285{
286 //
287 //resize buffer
288 //
289 if (fObjectSize<=0) {
290 cout<<"Object length not defined\n";
291 return;
292 }
293 if (fBufferSize>0) {
294 Resize2D(n); //if 2D buffer
295 return;
296 }
297 //
04fa961a 298 if (n>fCapacity) Reserve(2*n); //reserve automaticaly space if sie >capacity
08edbb90 299 if (fSize>n){
300 DTORBuffer(Unchecked1DAt(n),fSize-n);
e36f9c7d 301 //memset(&((char*)fCont)[n*fObjectSize], 0, (fSize-n)*fObjectSize);
302 //MI change - to have the same as in TClonesArray
08edbb90 303 }
304 if (fSize<n) CTORBuffer(Unchecked1DAt(fSize),n-fSize);
305 fSize = n;
306 return;
307}
308
309void AliMemArray::Delete2D()
310{
311 //
312 //delete memory space occupied by the array
313 if (!fBufferSize) return;
314
315 Int_t nbuff = (fCapacity/fBufferSize);
316 if ( (fCapacity%fBufferSize)!=0) nbuff++;
317 for (Int_t i=0;i<nbuff;i++) {
318 Int_t size = fSize-i*fBufferSize;
319 if (size>0)
320 DTORBuffer(GetRow(i),UInt_t(size)<fBufferSize? size:fBufferSize);
321 delete [] (char*)GetRow(i);
322 }
323 delete [] (void**)fCont;
324 fCont =0;
325 fSize = 0;
326 fCapacity = 0;
327}
328
329void AliMemArray::Clear2D()
330{
331 //
332 //clear memory space occupied by the array - doesn't call DTOR
333 Int_t nbuff = (fCapacity/fBufferSize);
334 if ( (fCapacity%fBufferSize)!=0) nbuff++;
e36f9c7d 335 // for (Int_t i=0;i<nbuff;i++) memset(GetRow(i), 0, fSize*fObjectSize);
336 //MI change - to have the same as in TClonesArray
08edbb90 337 fSize = 0;
338}
339
340
341
342
343void AliMemArray::Reserve2D(UInt_t n)
344{
345 //
346 //
347 Int_t buffers = n/fBufferSize;
348 if (n%fBufferSize) buffers++;
349 UInt_t nobjects=buffers*fBufferSize;
350 Int_t oldbuffers = GetNBuffers() ;
351 if (buffers==oldbuffers) return;
352 //
353 void ** table = (void**) new char*[buffers];
354
355 Int_t max = buffers>oldbuffers ? buffers: oldbuffers;
356 for (Int_t i = 0;i<max;i++) {
357 if ( (i<oldbuffers) && (i<buffers)) table[i] = GetRow(i);
358 if ( (i<oldbuffers)&&(i>=buffers) ){
359 Int_t dsize = TMath::Min(Int_t(fSize) - i*Int_t(fBufferSize),Int_t(fBufferSize));
360 if (dsize>0) DTORBuffer(GetRow(i),dsize);
361 delete [] (char*)GetRow(i);
362 }
363 if (i>=oldbuffers)
364 table[i] = new char[fBufferSize*fObjectSize];
365 }
366 if (fSize>nobjects) fSize=nobjects;
367
368 fCapacity = nobjects ;
369 delete [] (void**)fCont;
370 fCont = (void*)table;
371}
372
373
374
375void AliMemArray::Resize2D(UInt_t n)
376{
377 //
378 //
379 if (n>fCapacity) Reserve2D(n); //reserve automaticaly space
380 Int_t buffers = n/fBufferSize;
381 if (n%fBufferSize) buffers++;
382
383 if (fSize>n){ //call destructor if we decrease the size of array
384 Int_t oldbuffer = fSize/fBufferSize;
385
386 for (Int_t i=buffers;i<oldbuffer; i++){
387 Int_t iold= fSize-i*fBufferSize;
388 if (iold>(Int_t)fBufferSize) iold= fBufferSize;
389 Int_t inew= n -i*fBufferSize;
390 if (inew<0) inew =0;
391 DTORBuffer(Unchecked2DAt(i,inew),iold-inew);
392 }
393 }
394 if (fSize<n){ //call constructor if we increase the size of array
395 Int_t oldbuffer = fSize/fBufferSize;
396 for (Int_t i=oldbuffer;i<buffers; i++){
397 Int_t iold = fSize-i*fBufferSize;
398 if (iold<0) iold = 0;
399 Int_t inew = n -i*fBufferSize;
400 if (inew>(Int_t)fBufferSize) inew = fBufferSize;
401 CTORBuffer(Unchecked2DAt(i,iold),inew-iold);
402 }
403 }
404 fSize = n;
405}
406
407
408
409
410
411