/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ /* $Id$ */ /////////////////////////////////////////////////////////////////////////////// // // // AliMemArray // // (Pseudo)Container optimised for fast random access operator[ ]. // Operator [] time doesn’t depend on the number of elements in container O(1) - // like in standard array or like in STL vector // To achieve maximally-fast indexing and iteration in one buffer mode // the vector maintains its storage as a single contiguous array of objects (one buffer mode) // When a vector runs out of pre-allocated storage, in order to maintain it // contiguous array it must allocate a whole new (larger) chunk of storage // elsewhere and copy the objects to the new storage. // void * AliMemArray::Unchecked1DAt(UInt_t i) const // return &(((char*)fCont)[fObjectSize*i]); // In multi buffer mode (like two dimensional array) when a vector runs out of // pre-allocated storage we don’t need to copy whole array only small buffer but operator [] is slower // void * AliMemArray::Unchecked2DAt(UInt_t i, UInt_t j) const // return &( ((char**)fCont)[i] [j*fObjectSize]); // void * AliMemArray::Unchecked2DAt(UInt_t i) const // return &( ((char**)fCont)[i/fBufferSize] [(i%fBufferSize)*fObjectSize]) ; //Begin_Html // //End_Html // Streamer CTORBuffer and DTORBuffer are virtual - should be implemented in derived // classes. For example AliObjectArray derived from AliMemArray is general array // for objects with defined AliClassInfo information. // // // // // Origin: Marian Ivanov, Uni. of Bratislava, ivanov@fmph.uniba.sk // /////////////////////////////////////////////////////////////////////////////// #include "AliMemArray.h" #include "Riostream.h" #include "TMath.h" #include "TError.h" ClassImp(AliMemArray) AliMemArray::AliMemArray() { // //default constructor // fCont = 0; fSize = 0; fCapacity=0; fObjectSize = 0; fBufferSize = 0; } AliMemArray::AliMemArray(Int_t objectSize, Int_t buffersize) { // // AliMemArray constructor fCont = 0; fSize = 0; fCapacity=0; fObjectSize =objectSize; fBufferSize =buffersize; } AliMemArray::AliMemArray(const AliMemArray & arr): TObject(arr) { // //copy constructor fCont = arr.fCont; fSize = arr.fSize; fCapacity = arr.fCapacity; fObjectSize = arr.fObjectSize; fBufferSize =arr.fBufferSize; if (arr.fBufferSize==0) { fCont = new char[fCapacity*fObjectSize]; CopyBuffer(fCont, arr.fCont, fSize); } else{ Int_t buffers = fCapacity/fBufferSize; if (fCapacity%fBufferSize) buffers++; void ** table = (void**) new char*[buffers]; for (Int_t i=0; i (Int_t)fBufferSize) size = fBufferSize; if (size >0) CopyBuffer(table[i], ((void**)arr.fCont)[i],size); } fCont = (void*)table; } } void AliMemArray::Swap( AliMemArray &arr) { //swap contents of array UInt_t size = arr.fSize; arr.fSize = fSize; fSize = size; UInt_t capacity = arr.fCapacity; arr.fCapacity = fCapacity; fCapacity = capacity; UInt_t objectSize = arr.fObjectSize; arr.fObjectSize = fObjectSize; fObjectSize = objectSize; UInt_t bufferSize = arr.fBufferSize; arr.fBufferSize = fBufferSize; fBufferSize = bufferSize; void * cont = arr.fCont; arr.fCont = fCont; fCont = cont; } void AliMemArray::CopyBuffer(void *dest, void *src, UInt_t size) { // //array placement copy constructor memcpy(dest, src,size*fObjectSize); } AliMemArray::~AliMemArray() { // //default destructor Delete(); } void AliMemArray::SetObjectSize(UInt_t bufsize) { // //set memory size for one object - it can be changed only when the array is empty if (fCont){ ::Error("AliMemArray::SetObjectSize", "forbidden to resize just allocated objects"); return; }; fBufferSize=bufsize; } AliMemArray & AliMemArray::operator = (const AliMemArray &arr) { // // AliMemArray tmparr(arr); Swap(tmparr); return *this; } void AliMemArray::SetBufferSize(UInt_t bufsize) { // //set buffer size - it can be changed only when the array is empty if (fCont==0) { fBufferSize = bufsize; return; } if (fBufferSize == bufsize) return; if (bufsize==0){ char *table = new char[fObjectSize*fCapacity]; char * p = table; for (UInt_t i=0; i (Int_t)bufsize) size = bufsize; if (size >0) for ( Int_t ip=0;ip0) { Reserve2D(n); //if 2D buffer return; } // if (fCapacity){ if (fSize>n) { DTORBuffer(Unchecked1DAt(n),fSize-n); memset(&((char*)fCont)[n*fObjectSize], 0, (fSize-n)*fObjectSize); fSize =n; } fCont = (char*)TStorage::ReAlloc(fCont, n*fObjectSize,fCapacity*fObjectSize); } else fCont = new char[n*fObjectSize]; if (!fCont) fCapacity = 0; else fCapacity = n; } void AliMemArray::Resize(UInt_t n) { // //resize buffer // if (fObjectSize<=0) { cout<<"Object length not defined\n"; return; } if (fBufferSize>0) { Resize2D(n); //if 2D buffer return; } // if (n>fCapacity) Reserve(2*n); //reserve automaticaly space if sie >capacity if (fSize>n){ DTORBuffer(Unchecked1DAt(n),fSize-n); //memset(&((char*)fCont)[n*fObjectSize], 0, (fSize-n)*fObjectSize); //MI change - to have the same as in TClonesArray } if (fSize0) DTORBuffer(GetRow(i),UInt_t(size)oldbuffers ? buffers: oldbuffers; for (Int_t i = 0;i=buffers) ){ Int_t dsize = TMath::Min(Int_t(fSize) - i*Int_t(fBufferSize),Int_t(fBufferSize)); if (dsize>0) DTORBuffer(GetRow(i),dsize); delete [] (char*)GetRow(i); } if (i>=oldbuffers) table[i] = new char[fBufferSize*fObjectSize]; } if (fSize>nobjects) fSize=nobjects; fCapacity = nobjects ; delete [] (void**)fCont; fCont = (void*)table; } void AliMemArray::Resize2D(UInt_t n) { // // if (n>fCapacity) Reserve2D(n); //reserve automaticaly space Int_t buffers = n/fBufferSize; if (n%fBufferSize) buffers++; if (fSize>n){ //call destructor if we decrease the size of array Int_t oldbuffer = fSize/fBufferSize; for (Int_t i=buffers;i(Int_t)fBufferSize) iold= fBufferSize; Int_t inew= n -i*fBufferSize; if (inew<0) inew =0; DTORBuffer(Unchecked2DAt(i,inew),iold-inew); } } if (fSize(Int_t)fBufferSize) inew = fBufferSize; CTORBuffer(Unchecked2DAt(i,iold),inew-iold); } } fSize = n; }