ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/DataCont/interface/FastArray.h
Revision: 1.2
Committed: Fri Feb 27 09:16:30 2009 UTC (16 years, 2 months ago) by bendavid
Content type: text/plain
Branch: MAIN
Changes since 1.1: +3 -3 lines
Log Message:
Fixed FastArray copy ctor bugs

File Contents

# User Rev Content
1 bendavid 1.1 //--------------------------------------------------------------------------------------------------
2 bendavid 1.2 // $Id: FastArray.h,v 1.1 2009/02/26 17:05:18 bendavid Exp $
3 bendavid 1.1 //
4     // FastArray
5     //
6     // Implementation of an array on the heap. Memory is dynamically allocated,
7     // but there is an optimization in the read streamer similar to the TClonesArray
8     // where the heap memory of an existing object is reused. This class is meant to be used
9     // as a datamember for objects which are contained inside a TClonesArray.
10     // For various reasons, the array can not be written in split
11     // mode. Array is meant to store classes as opposed to FastArrayBasic which should be used to
12     // hold basic types.
13     //
14     // Authors: J.Bendavid
15     //--------------------------------------------------------------------------------------------------
16    
17     #ifndef MITANA_DATACONT_FASTARRAY
18     #define MITANA_DATACONT_FASTARRAY
19    
20     #include <TObject.h>
21     #include <TClass.h>
22     #include <TStorage.h>
23     #include "MitAna/DataCont/interface/Collection.h"
24    
25     namespace mithep
26     {
27     template<class ArrayElement>
28     class FastArray : public Collection<ArrayElement>
29     {
30     public:
31     FastArray();
32     FastArray(const FastArray &a);
33     ~FastArray() { Init(0); }
34    
35     void AddCopy(const ArrayElement &ae);
36     ArrayElement *AddNew();
37     ArrayElement *Allocate();
38     ArrayElement *At(UInt_t idx);
39     const ArrayElement *At(UInt_t idx) const;
40     void Clear(Option_t */*opt*/="") { fSize=0; Init(0); }
41     UInt_t Entries() const { return GetEntries(); }
42     UInt_t GetEntries() const { return fSize; }
43     ArrayElement *GetNew();
44     UInt_t GetSize() const { return fCapacity; }
45     Bool_t HasObject(const ArrayElement *obj) const;
46     Bool_t IsOwner() const { return kTRUE; }
47     TObject *ObjAt(UInt_t idx);
48     const TObject *ObjAt(UInt_t idx) const;
49     void Reset() { fSize = 0; }
50     void Trim() { Expand(fSize); }
51     ArrayElement *UncheckedAt(UInt_t idx);
52     const ArrayElement *UncheckedAt(UInt_t idx) const;
53     ArrayElement *operator[](UInt_t idx);
54     const ArrayElement *operator[](UInt_t idx) const;
55    
56     protected:
57     ArrayElement *AddBlank();
58     void Init(UShort_t s);
59     void Expand(UShort_t s);
60    
61     TClass *fClass; //!pointer to TClass object used by streamer
62     UShort_t fSize; //size of array
63     UShort_t fCapacity; //!size of heap allocated
64     UShort_t fNObjects; //!number of allocated objects
65     ArrayElement *fArray; //!
66    
67     ClassDef(FastArray,1) // Array on stack for arbitrary classes
68     };
69     }
70    
71     //--------------------------------------------------------------------------------------------------
72     template<class ArrayElement>
73     inline mithep::FastArray<ArrayElement>::FastArray() :
74     fClass(TClass::GetClass(typeid(ArrayElement))),
75     fSize(0),
76     fCapacity(0),
77     fNObjects(0),
78     fArray(0)
79     {
80     // Default constructor.
81     }
82    
83     //--------------------------------------------------------------------------------------------------
84     template<class ArrayElement>
85     inline mithep::FastArray<ArrayElement>::FastArray(const FastArray &a) :
86     fClass(a.fClass),
87 bendavid 1.2 fSize(0),
88 bendavid 1.1 fCapacity(0),
89     fNObjects(0),
90     fArray(0)
91     {
92     // Copy constructor. Copy only elements which are used.
93 bendavid 1.2 Init(a.fSize);
94 bendavid 1.1
95     for (UInt_t i=0; i<a.fSize; ++i)
96     new(Allocate()) ArrayElement(a.fArray[i]);
97     }
98    
99     //--------------------------------------------------------------------------------------------------
100     template<class ArrayElement>
101     ArrayElement* mithep::FastArray<ArrayElement>::AddBlank()
102     {
103     // Construct additional blank objects for read streamer
104    
105     if (fNObjects >= fCapacity)
106     Expand(TMath::Max(16,2*fCapacity));
107    
108     ++fNObjects;
109     return new(&fArray[fNObjects-1]) ArrayElement();
110     }
111    
112     //--------------------------------------------------------------------------------------------------
113     template<class ArrayElement>
114     void mithep::FastArray<ArrayElement>::AddCopy(const ArrayElement &ae)
115     {
116     // Add a copy of an existing object.
117    
118     if (fSize<fNObjects) {
119     fArray[fSize] = ae;
120     ++fSize;
121     }
122     else
123     new(Allocate()) ArrayElement(ae);
124     }
125    
126     //--------------------------------------------------------------------------------------------------
127     template<class ArrayElement>
128     ArrayElement* mithep::FastArray<ArrayElement>::AddNew()
129     {
130     // Add new object.
131    
132     return new(Allocate()) ArrayElement();
133     }
134    
135     //--------------------------------------------------------------------------------------------------
136     template<class ArrayElement>
137     ArrayElement* mithep::FastArray<ArrayElement>::Allocate()
138     {
139     // Return next slot in the array, *only* to be used in placement new operator.
140    
141     if (fSize >= fCapacity)
142     Expand(TMath::Max(16,2*fCapacity));
143    
144     ++fSize;
145     fNObjects = TMath::Max(fNObjects,fSize);
146     return &fArray[fSize-1];
147    
148     }
149    
150     //--------------------------------------------------------------------------------------------------
151     template<class ArrayElement>
152     inline ArrayElement *mithep::FastArray<ArrayElement>::At(UInt_t idx)
153     {
154     // Return entry at given index.
155    
156     if (idx<fSize)
157     return static_cast<ArrayElement*>(&fArray[idx]);
158    
159     ArrayElement tmp;
160     TObject::Fatal("At","Index too large: (%u < %u violated) for %s containing %s",
161     idx, fSize, this->GetName(), typeid(tmp).name());
162     return 0;
163     }
164    
165     //--------------------------------------------------------------------------------------------------
166     template<class ArrayElement>
167     inline const ArrayElement *mithep::FastArray<ArrayElement>::At(UInt_t idx) const
168     {
169     // Return entry at given index.
170    
171     if (idx<fSize)
172     return static_cast<const ArrayElement*>(&fArray[idx]);
173    
174     ArrayElement tmp;
175     TObject::Fatal("At","Index too large: (%u < %u violated) for %s containing %s",
176     idx, fSize, this->GetName(), typeid(tmp).name());
177     return 0;
178     }
179    
180     //--------------------------------------------------------------------------------------------------
181     template<class ArrayElement>
182     inline void mithep::FastArray<ArrayElement>::Expand(UShort_t s)
183     {
184    
185     // Expand or shrink the array to s elements.
186    
187     if (s < fSize) {
188     TObject::Fatal("Expand", "Cannot shrink FastArray to less than fSize");
189     return;
190     }
191    
192     if (!fArray || s==0) {
193     Init(s);
194     return;
195     }
196    
197     if (fCapacity == s)
198     return;
199    
200     fArray = static_cast<ArrayElement*>(TStorage::ReAlloc(fArray, s * sizeof(ArrayElement),
201     fCapacity * sizeof(ArrayElement)));
202     fCapacity = s;
203     fNObjects = TMath::Min(fCapacity,fNObjects);
204    
205     }
206    
207     //--------------------------------------------------------------------------------------------------
208     template<class ArrayElement>
209     ArrayElement* mithep::FastArray<ArrayElement>::GetNew()
210     {
211     // Return next slot in the array, *only* to be used in placement new operator.
212    
213     if (fSize < fCapacity)
214     return Allocate();
215     else
216     return AddNew();
217    
218     }
219    
220     //--------------------------------------------------------------------------------------------------
221     template<class ArrayElement>
222     inline Bool_t mithep::FastArray<ArrayElement>::HasObject(const ArrayElement *obj) const
223     {
224     // Check whether object is in array.
225    
226     for (UInt_t i=0; i<fSize; ++i) {
227     if ( fArray[i].IsEqual(obj) )
228     return true;
229     }
230    
231     return false;
232     }
233    
234     //--------------------------------------------------------------------------------------------------
235     template<class ArrayElement>
236     inline void mithep::FastArray<ArrayElement>::Init(UShort_t s)
237     {
238    
239     // Initialize heap array
240    
241     if (fArray && fCapacity != s) {
242     for (UInt_t i=0; i<fNObjects; ++i)
243     fArray[i].~ArrayElement();
244     TStorage::Dealloc(fArray);
245     fArray = 0;
246     fNObjects = 0;
247     }
248    
249     fCapacity = s;
250    
251     if ( !fArray && fCapacity > 0 )
252     fArray = static_cast<ArrayElement*>(TStorage::Alloc(fCapacity*sizeof(ArrayElement))); //new TObject* [fSize];
253     //memset(fCont, 0, fSize*sizeof(TObject*));
254    
255     }
256    
257     //--------------------------------------------------------------------------------------------------
258     template<class ArrayElement>
259     inline TObject *mithep::FastArray<ArrayElement>::ObjAt(UInt_t idx)
260     {
261     // Return object at given index.
262    
263     return static_cast<TObject*>(At(idx));
264     }
265    
266     //--------------------------------------------------------------------------------------------------
267     template<class ArrayElement>
268     inline const TObject *mithep::FastArray<ArrayElement>::ObjAt(UInt_t idx) const
269     {
270     // Return object at given index.
271    
272     return static_cast<const TObject*>(At(idx));
273     }
274    
275     //-------------------------------------------------------------------------------------------------
276     template<class ArrayElement>
277     void mithep::FastArray<ArrayElement>::Streamer(TBuffer &b)
278     {
279     // Stream all objects in the array to or from the I/O buffer.
280    
281     if (b.IsReading()) {
282     b >> fSize;
283     if (fSize) {
284     if (fSize > fCapacity)
285     Expand(TMath::Max(static_cast<Int_t>(fSize),2*fCapacity));
286    
287     while (fNObjects < fSize)
288     AddBlank();
289    
290     b.ReadFastArray(fArray,fClass,fSize);
291     }
292     } else { /*writing*/
293     b << fSize;
294     if (fSize) {
295     b.WriteFastArray(fArray,fClass,fSize);
296     }
297     }
298     }
299    
300     //--------------------------------------------------------------------------------------------------
301     template<class ArrayElement>
302     inline ArrayElement *mithep::FastArray<ArrayElement>::UncheckedAt(UInt_t idx)
303     {
304     // Return entry at given index.
305    
306     return static_cast<ArrayElement*>(&fArray[idx]);
307     }
308    
309     //--------------------------------------------------------------------------------------------------
310     template<class ArrayElement>
311     inline const ArrayElement *mithep::FastArray<ArrayElement>::UncheckedAt(UInt_t idx) const
312     {
313     // Return entry at given index.
314    
315     return static_cast<const ArrayElement*>(&fArray[idx]);
316     }
317    
318     //--------------------------------------------------------------------------------------------------
319     template<class ArrayElement>
320     inline const ArrayElement *mithep::FastArray<ArrayElement>::operator[](UInt_t idx) const
321     {
322     // Return entry at given index.
323    
324     return At(idx);
325     }
326    
327     //--------------------------------------------------------------------------------------------------
328     template<class ArrayElement>
329     inline ArrayElement *mithep::FastArray<ArrayElement>::operator[](UInt_t idx)
330     {
331     // Return entry at given index.
332    
333     return At(idx);
334     }
335     #endif