Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGenCollectionProxy.h
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Markus Frank 28/10/04
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 #ifndef ROOT_TGenCollectionProxy
12 #define ROOT_TGenCollectionProxy
13 
14 #include "TBuffer.h"
15 
17 
18 #include "TCollectionProxyInfo.h"
19 
20 #include <atomic>
21 #include <string>
22 #include <map>
23 #include <stdlib.h>
24 
25 class TObjArray;
26 class TCollectionProxyFactory;
27 
28 class TGenCollectionProxy
29  : public TVirtualCollectionProxy
30 {
31 
32  // Friend declaration
33  friend class TCollectionProxyFactory;
34 
35 public:
36 
37 #ifdef R__HPUX
38  typedef const std::type_info& Info_t;
39 #else
40  typedef const std::type_info& Info_t;
41 #endif
42 
43  enum {
44  // Those 'bits' are used in conjunction with CINT's bit to store the 'type'
45  // info into one int
46  kBIT_ISSTRING = 0x20000000, // We can optimized a value operation when the content are strings
47  kBIT_ISTSTRING = 0x40000000
48  };
49 
50  /** @class TGenCollectionProxy::Value TGenCollectionProxy.h TGenCollectionProxy.h
51  *
52  * Small helper to describe the Value_type or the key_type
53  * of an STL container.
54  *
55  * @author M.Frank
56  * @version 1.0
57  * @date 10/10/2004
58  */
59  struct Value {
60  ROOT::NewFunc_t fCtor; ///< Method cache for containee constructor
61  ROOT::DesFunc_t fDtor; ///< Method cache for containee destructor
62  ROOT::DelFunc_t fDelete; ///< Method cache for containee delete
63  UInt_t fCase; ///< type of data of Value_type
64  UInt_t fProperties; ///< Additional properties of the value type (kNeedDelete)
65  TClassRef fType; ///< TClass reference of Value_type in collection
66  EDataType fKind; ///< kind of ROOT-fundamental type
67  size_t fSize; ///< fSize of the contained object
68 
69  // Default copy constructor has the correct implementation.
70 
71  // Initializing constructor
72  Value(const std::string& info, Bool_t silent);
73  // Delete individual item from STL container
74  void DeleteItem(void* ptr);
75 
76  Bool_t IsValid();
77  };
78 
79  /**@class StreamHelper
80  *
81  * Helper class to facilitate I/O
82  *
83  * @author M.Frank
84  * @version 1.0
85  * @date 10/10/2004
86  */
87  union StreamHelper {
88  Bool_t boolean;
89  Char_t s_char;
90  Short_t s_short;
91  Int_t s_int;
92  Long_t s_long;
93  Long64_t s_longlong;
94  Float_t flt;
95  Double_t dbl;
96  UChar_t u_char;
97  UShort_t u_short;
98  UInt_t u_int;
99  ULong_t u_long;
100  ULong64_t u_longlong;
101  void* p_void;
102  void** pp_void;
103  char* kchar;
104  TString* tstr;
105  void* ptr() {
106  return *(&this->p_void);
107  }
108  std::string* str() {
109  return (std::string*)this;
110  }
111  const char* c_str() {
112  return ((std::string*)this)->c_str();
113  }
114  const char* c_pstr() {
115  return (*(std::string**)this)->c_str();
116  }
117  void set(void* p) {
118  *(&this->p_void) = p;
119  }
120  void read_std_string(TBuffer& b) {
121  TString s;
122  s.Streamer(b);
123  ((std::string*)this)->assign(s.Data());
124  }
125  void* read_tstring(TBuffer& b) {
126  *((TString*)this) = "";
127  ((TString*)this)->Streamer(b);
128  return this;
129  }
130  void read_std_string_pointer(TBuffer& b) {
131  TString s;
132  std::string* str2 = (std::string*)ptr();
133  if (!str2) str2 = new std::string();
134  s.Streamer(b);
135  *str2 = s;
136  set(str2);
137  }
138  void write_std_string_pointer(TBuffer& b) {
139  const char* c;
140  if (ptr()) {
141  std::string* strptr = (*(std::string**)this);
142  c = (const char*)(strptr->c_str());
143  } else c = "";
144  TString(c).Streamer(b);
145  }
146  void read_any_object(Value* v, TBuffer& b) {
147  void* p = ptr();
148  if ( p ) {
149  if ( v->fDelete ) { // Compiled content: call Destructor
150  (*v->fDelete)(p);
151  }
152  else if ( v->fType ) { // Emulated content: call TClass::Delete
153  v->fType->Destructor(p);
154  }
155  else if ( v->fDtor ) {
156  (*v->fDtor)(p);
157  ::operator delete(p);
158  }
159  else {
160  ::operator delete(p);
161  }
162  }
163  set( b.ReadObjectAny(v->fType) );
164  }
165 
166  void read_tstring_pointer(Bool_t vsn3, TBuffer& b) {
167  TString* s = (TString*)ptr();
168  if ( vsn3 ) {
169  if ( !s ) s = new TString();
170  else s->Clear();
171  s->Streamer(b);
172  set(s);
173  return;
174  }
175  if ( s ) delete s;
176  set( b.ReadObjectAny(TString::Class()) );
177  }
178  void write_tstring_pointer(TBuffer& b) {
179  b.WriteObjectAny(ptr(), TString::Class());
180  }
181  };
182 
183  /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h
184  *
185  * Small helper to execute (compiler) generated function for the
186  * access to STL or other containers.
187  *
188  * @author M.Frank
189  * @version 1.0
190  * @date 10/10/2004
191  */
192  class Method {
193  public:
194  typedef void* (*Call_t)(void*);
195  Call_t call;
196  Method() : call(0) { }
197  Method(Call_t c) : call(c) { }
198  Method(const Method& m) : call(m.call) { }
199  Method &operator=(const Method& m) { call = m.call; return *this; }
200  void* invoke(void* obj) const { return (*call)(obj); }
201  };
202 
203  /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h
204  *
205  * Small helper to execute (compiler) generated function for the
206  * access to STL or other containers.
207  *
208  * @author M.Frank
209  * @version 1.0
210  * @date 10/10/2004
211  */
212  class Method0 {
213  public:
214  typedef void* (*Call_t)();
215  Call_t call;
216  Method0() : call(0) { }
217  Method0(Call_t c) : call(c) { }
218  Method0(const Method0& m) : call(m.call) { }
219  Method0 &operator=(const Method0& m) { call = m.call; return *this; }
220  void* invoke() const { return (*call)(); }
221  };
222 
223  /** @class TGenCollectionProxy::TStaging
224  *
225  * Small helper to stage the content of an associative
226  * container when reading and before inserting it in the
227  * actual collection.
228  *
229  * @author Ph.Canal
230  * @version 1.0
231  * @date 20/08/2010
232  */
233  class TStaging {
234  void *fTarget; ///< Pointer to the collection we are staging for.
235  void *fContent; ///< Pointer to the content
236  size_t fReserved; ///< Amount of space already reserved.
237  size_t fSize; ///< Number of elements
238  size_t fSizeOf; ///< size of each elements
239 
240  TStaging(const TStaging&); ///< Not implemented.
241  TStaging &operator=(const TStaging&); ///< Not implemented.
242 
243  public:
244  TStaging(size_t size, size_t size_of) : fTarget(0), fContent(0), fReserved(0), fSize(size), fSizeOf(size_of)
245  {
246  // Usual constructor. Reserves the required number of elements.
247  fReserved = fSize;
248  fContent = ::malloc(fReserved * fSizeOf);
249  }
250 
251  ~TStaging() {
252  // Usual destructor
253  ::free(fContent);
254  }
255 
256  void *GetContent() {
257  // Return the location of the array of content.
258  return fContent;
259  }
260  void *GetEnd() {
261  // Return the 'end' of the array of content.
262  return ((char*)fContent) + fSize*fSizeOf;
263  }
264  size_t GetSize() {
265  // Return the number of elements.
266  return fSize;
267  }
268  void *GetTarget() {
269  // Get the address of the collection we are staging for.
270  return fTarget;
271  }
272  void Resize(size_t nelement) {
273  if (fReserved < nelement) {
274  fReserved = nelement;
275  fContent = ::realloc(fContent,fReserved * fSizeOf);
276  }
277  fSize = nelement;
278  }
279  void SetTarget(void *target) {
280  // Set the collection we are staging for.
281  fTarget = target;
282  }
283  };
284 
285 protected:
286  typedef ROOT::Detail::TCollectionProxyInfo::Environ<char[64]> Env_t;
287  typedef ROOT::Detail::TCollectionProxyInfo::EnvironBase EnvironBase_t;
288  typedef std::vector<TStaging*> Staged_t; ///< Collection of pre-allocated staged array for associative containers.
289  typedef std::vector<EnvironBase_t*> Proxies_t;
290  mutable TObjArray *fReadMemberWise; ///< Array of bundle of TStreamerInfoActions to stream out (read)
291  mutable std::map<std::string, TObjArray*> *fConversionReadMemberWise; ///< Array of bundle of TStreamerInfoActions to stream out (read) derived from another class.
292  mutable TStreamerInfoActions::TActionSequence *fWriteMemberWise;
293  typedef void (*Sizing_t)(void *obj, size_t size);
294  typedef void* (*Feedfunc_t)(void *from, void *to, size_t size);
295  typedef void* (*Collectfunc_t)(void *from, void *to);
296  typedef void* (*ArrIterfunc_t)(void *from, size_t size);
297 
298  std::string fName; ///< Name of the class being proxied.
299  Bool_t fPointers; ///< Flag to indicate if containee has pointers (key or value)
300  Method fClear; ///< Method cache for container accessors: clear container
301  Method fSize; ///< Container accessors: size of container
302  Sizing_t fResize; ///< Container accessors: resize container
303  Method fFirst; ///< Container accessors: generic iteration: first
304  Method fNext; ///< Container accessors: generic iteration: next
305  ArrIterfunc_t fConstruct; ///< Container accessors: block construct
306  Sizing_t fDestruct; ///< Container accessors: block destruct
307  Feedfunc_t fFeed; ///< Container accessors: block feed
308  Collectfunc_t fCollect; ///< Method to collect objects from container
309  Method0 fCreateEnv; ///< Method to allocate an Environment holder.
310  std::atomic<Value*> fValue; ///< Descriptor of the container value type
311  Value* fVal; ///< Descriptor of the Value_type
312  Value* fKey; ///< Descriptor of the key_type
313  EnvironBase_t*fEnv; ///< Address of the currently proxied object
314  int fValOffset; ///< Offset from key to value (in maps)
315  int fValDiff; ///< Offset between two consecutive value_types (memory layout).
316  Proxies_t fProxyList; ///< Stack of recursive proxies
317  Proxies_t fProxyKept; ///< Optimization: Keep proxies once they were created
318  Staged_t fStaged; ///< Optimization: Keep staged array once they were created
319  int fSTL_type; ///< STL container type
320  Info_t fTypeinfo; ///< Type information
321  TClass* fOnFileClass; ///< On file class
322 
323  CreateIterators_t fFunctionCreateIterators;
324  CopyIterator_t fFunctionCopyIterator;
325  Next_t fFunctionNextIterator;
326  DeleteIterator_t fFunctionDeleteIterator;
327  DeleteTwoIterators_t fFunctionDeleteTwoIterators;
328 
329  // Late initialization of collection proxy
330  TGenCollectionProxy* Initialize(Bool_t silent) const;
331  // Some hack to avoid const-ness.
332  virtual TGenCollectionProxy* InitializeEx(Bool_t silent);
333  // Call to delete/destruct individual contained item.
334  virtual void DeleteItem(Bool_t force, void* ptr) const;
335  // Allow to check function pointers.
336  void CheckFunctions() const;
337 
338  // Set pointer to the TClass representing the content.
339  virtual void UpdateValueClass(const TClass *oldcl, TClass *newcl);
340 
341 private:
342  TGenCollectionProxy(); // not implemented on purpose.
343 
344 public:
345 
346  // Virtual copy constructor.
347  virtual TVirtualCollectionProxy* Generate() const;
348 
349  // Copy constructor.
350  TGenCollectionProxy(const TGenCollectionProxy& copy);
351 
352 private:
353  // Assignment operator
354  TGenCollectionProxy &operator=(const TGenCollectionProxy&); // Not Implemented
355 
356 public:
357  // Initializing constructor
358  TGenCollectionProxy(Info_t typ, size_t iter_size);
359  TGenCollectionProxy(const ROOT::Detail::TCollectionProxyInfo &info, TClass *cl);
360 
361  // Standard destructor.
362  virtual ~TGenCollectionProxy();
363 
364  // Return a pointer to the TClass representing the container.
365  virtual TClass *GetCollectionClass() const;
366 
367  // Return the type of collection see TClassEdit::ESTLType
368  virtual Int_t GetCollectionType() const;
369 
370  // Return the offset between two consecutive value_types (memory layout).
371  virtual ULong_t GetIncrement() const;
372 
373  // Return the sizeof the collection object.
374  virtual UInt_t Sizeof() const;
375 
376  // Push new proxy environment.
377  virtual void PushProxy(void *objstart);
378 
379  // Pop old proxy environment.
380  virtual void PopProxy();
381 
382  // Return true if the content is of type 'pointer to'.
383  virtual Bool_t HasPointers() const;
384 
385  // Return a pointer to the TClass representing the content.
386  virtual TClass *GetValueClass() const;
387 
388  // If the content is a simple numerical value, return its type (see TDataType).
389  virtual EDataType GetType() const;
390 
391  // Return the address of the value at index 'idx'.
392  virtual void *At(UInt_t idx);
393 
394  // Clear the container.
395  virtual void Clear(const char *opt = "");
396 
397  // Resize the container.
398  virtual void Resize(UInt_t n, Bool_t force_delete);
399 
400  // Return the current size of the container.
401  virtual UInt_t Size() const;
402 
403  // Block allocation of containees.
404  virtual void* Allocate(UInt_t n, Bool_t forceDelete);
405 
406  // Insert data into the container where data is a C-style array of the actual type contained in the collection
407  // of the given size. For associative container (map, etc.), the data type is the pair<key,value>.
408  virtual void Insert(const void *data, void *container, size_t size);
409 
410  // Block commit of containees.
411  virtual void Commit(void* env);
412 
413  // Streamer function.
414  virtual void Streamer(TBuffer &refBuffer);
415 
416  // Streamer I/O overload.
417  virtual void Streamer(TBuffer &refBuffer, void *pObject, int siz);
418 
419  // TClassStreamer I/O overload.
420  virtual void operator()(TBuffer &refBuffer, void *pObject);
421 
422  // Routine to read the content of the buffer into 'obj'.
423  virtual void ReadBuffer(TBuffer &b, void *obj);
424  virtual void ReadBuffer(TBuffer &b, void *obj, const TClass *onfileClass);
425 
426  virtual void SetOnFileClass( TClass* cl ) { fOnFileClass = cl; }
427  virtual TClass* GetOnFileClass() const { return fOnFileClass; }
428 
429  // MemberWise actions
430  virtual TStreamerInfoActions::TActionSequence *GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version);
431  virtual TStreamerInfoActions::TActionSequence *GetReadMemberWiseActions(Int_t version);
432  virtual TStreamerInfoActions::TActionSequence *GetWriteMemberWiseActions();
433 
434  // Set of functions to iterate easily throught the collection
435 
436  virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read = kTRUE);
437  // typedef void (*CreateIterators_t)(void *collection, void **begin_arena, void **end_arena);
438  // begin_arena and end_arena should contain the location of a memory arena of size fgIteratorSize.
439  // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
440  // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
441 
442  virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read = kTRUE);
443  // typedef void* (*CopyIterator_t)(void **dest, const void *source);
444  // Copy the iterator source, into dest. dest should contain the location of a memory arena of size fgIteratorSize.
445  // If the collection iterator is of that size or less, the iterator will be constructed in place in this location (new with placement)
446  // Otherwise the iterator will be allocated via a regular new.
447  // The actual address of the iterator is returned in both case.
448 
449  virtual Next_t GetFunctionNext(Bool_t read = kTRUE);
450  // typedef void* (*Next_t)(void *iter, const void *end);
451  // iter and end should be pointers to respectively an iterator to be incremented and the result of collection.end()
452  // If the iterator has not reached the end of the collection, 'Next' increment the iterator 'iter' and return 0 if
453  // the iterator reached the end.
454  // If the end was not reached, 'Next' returns the address of the content pointed to by the iterator before the
455  // incrementation ; if the collection contains pointers, 'Next' will return the value of the pointer.
456 
457  virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read = kTRUE);
458  virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read = kTRUE);
459  // typedef void (*DeleteIterator_t)(void *iter);
460  // typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
461  // If the size of the iterator is greater than fgIteratorArenaSize, call delete on the addresses,
462  // Otherwise just call the iterator's destructor.
463 
464 };
465 
466 template <typename T>
467 struct AnyCollectionProxy : public TGenCollectionProxy {
468  AnyCollectionProxy()
469  : TGenCollectionProxy(typeid(T::Cont_t),sizeof(T::Iter_t))
470  {
471  // Constructor.
472  fValDiff = sizeof(T::Value_t);
473  fValOffset = T::value_offset();
474  fSize.call = T::size;
475  fResize = T::resize;
476  fNext.call = T::next;
477  fFirst.call = T::first;
478  fClear.call = T::clear;
479  fConstruct = T::construct;
480  fDestruct = T::destruct;
481  fFeed = T::feed;
482  CheckFunctions();
483  }
484  virtual ~AnyCollectionProxy() { }
485 };
486 
487 #endif
488