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