Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TStreamerInfoActions.h
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Philippe Canal 05/2010
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 
12 #ifndef ROOT_TStreamerInfoActions
13 #define ROOT_TStreamerInfoActions
14 
15 #include <vector>
16 #include <ROOT/RMakeUnique.hxx>
17 
18 #include "TStreamerInfo.h"
19 #include "TVirtualArray.h"
20 #include <assert.h>
21 
22 /**
23 \class TStreamerInfoActions::TConfiguration
24 \ingroup IO
25 */
26 
27 namespace TStreamerInfoActions {
28 
29  /// Base class of the Configurations.
30  class TConfiguration {
31  protected:
32  public:
33  typedef TStreamerInfo::TCompInfo_t TCompInfo_t;
34  TVirtualStreamerInfo *fInfo; ///< TStreamerInfo form which the action is derived
35  UInt_t fElemId; ///< Identifier of the TStreamerElement
36  TCompInfo_t *fCompInfo;///< Access to compiled information (for legacy code)
37  Int_t fOffset; ///< Offset within the object
38  UInt_t fLength; ///< Number of element in a fixed length array.
39  public:
40  TConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset) : fInfo(info), fElemId(id), fCompInfo(compinfo), fOffset(offset),fLength(1) {};
41  TConfiguration(TVirtualStreamerInfo *info, UInt_t id, TCompInfo_t *compinfo, Int_t offset, UInt_t length) : fInfo(info), fElemId(id), fCompInfo(compinfo), fOffset(offset),fLength(length) {};
42  virtual ~TConfiguration() {};
43 
44  virtual void AddToOffset(Int_t delta);
45  virtual void SetMissing();
46 
47  virtual TConfiguration *Copy() { return new TConfiguration(*this); }
48 
49  virtual void Print() const;
50  virtual void PrintDebug(TBuffer &buffer, void *object) const;
51  };
52 
53  /// Base class of the Configurations for the member wise looping routines.
54  class TLoopConfiguration {
55  public:
56  TVirtualCollectionProxy *fProxy = nullptr;
57  public:
58  TLoopConfiguration() = default;
59  TLoopConfiguration(TVirtualCollectionProxy *proxy) : fProxy(proxy) {}
60 
61  // virtual void PrintDebug(TBuffer &buffer, void *object) const;
62  virtual ~TLoopConfiguration() {};
63  virtual void Print() const;
64  virtual void *GetFirstAddress(void *start, const void *end) const = 0;
65  virtual TLoopConfiguration* Copy() const = 0; // { return new TLoopConfiguration(*this); }
66  virtual TVirtualCollectionProxy* GetCollectionProxy() const { return fProxy; }
67  };
68 
69  typedef TVirtualCollectionProxy::Next_t Next_t;
70 
71  typedef Int_t (*TStreamerInfoAction_t)(TBuffer &buf, void *obj, const TConfiguration *conf);
72  typedef Int_t (*TStreamerInfoVecPtrLoopAction_t)(TBuffer &buf, void *iter, const void *end, const TConfiguration *conf);
73  typedef Int_t (*TStreamerInfoLoopAction_t)(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf);
74 
75  class TConfiguredAction : public TObject {
76  public:
77  union {
78  TStreamerInfoAction_t fAction;
79  TStreamerInfoVecPtrLoopAction_t fVecPtrLoopAction;
80  TStreamerInfoLoopAction_t fLoopAction;
81  };
82  TConfiguration *fConfiguration;
83  private:
84  // assignment operator must be the default because the 'copy' constructor is actually a move constructor and must be used.
85  public:
86  TConfiguredAction() : fAction(0), fConfiguration(0) {}
87  TConfiguredAction(const TConfiguredAction &rval) : TObject(rval), fAction(rval.fAction), fConfiguration(rval.fConfiguration)
88  {
89  // WARNING: Technically this is a move constructor ...
90  const_cast<TConfiguredAction&>(rval).fConfiguration = 0;
91  }
92  TConfiguredAction &operator=(const TConfiguredAction &rval)
93  {
94  // WARNING: Technically this is a move assignment!.
95 
96  TConfiguredAction tmp(rval); // this does a move.
97  TObject::operator=(tmp); // we are missing TObject::Swap
98  std::swap(fAction,tmp.fAction);
99  std::swap(fConfiguration,tmp.fConfiguration);
100  return *this;
101  };
102 
103  TConfiguredAction(TStreamerInfoAction_t action, TConfiguration *conf) : fAction(action), fConfiguration(conf)
104  {
105  // Usual constructor.
106  }
107  TConfiguredAction(TStreamerInfoVecPtrLoopAction_t action, TConfiguration *conf) : fVecPtrLoopAction(action), fConfiguration(conf)
108  {
109  // Usual constructor.
110  }
111  TConfiguredAction(TStreamerInfoLoopAction_t action, TConfiguration *conf) : fLoopAction(action), fConfiguration(conf)
112  {
113  // Usual constructor.
114  }
115  ~TConfiguredAction() {
116  // Usual destructor.
117  // Idea: the configuration ownership might be moved to a single list so that
118  // we can shared them between the optimized and non-optimized list of actions.
119  delete fConfiguration;
120  }
121  void PrintDebug(TBuffer &buffer, void *object) const;
122 
123  inline Int_t operator()(TBuffer &buffer, void *object) const {
124  return fAction(buffer, object, fConfiguration);
125  }
126 
127  inline Int_t operator()(TBuffer &buffer, void *start_collection, const void *end_collection) const {
128  return fVecPtrLoopAction(buffer, start_collection, end_collection, fConfiguration);
129  }
130 
131  inline Int_t operator()(TBuffer &buffer, void *start_collection, const void *end_collection, const TLoopConfiguration *loopconf) const {
132  return fLoopAction(buffer, start_collection, end_collection, loopconf, fConfiguration);
133  }
134 
135  ClassDef(TConfiguredAction,0); // A configured action
136  };
137 
138  struct TIDNode;
139  using TIDs = std::vector<TIDNode>;
140 
141  // Hold information about unfolded/extracted StreamerElement for
142  // a sub-object
143  struct TNestedIDs {
144  TNestedIDs() = default;
145  TNestedIDs(TStreamerInfo *info, Int_t offset) : fInfo(info), fOffset(offset) {}
146  ~TNestedIDs() {
147  if (fOwnOnfileObject)
148  delete fOnfileObject;
149  }
150  TStreamerInfo *fInfo = nullptr; ///< Not owned.
151  TVirtualArray *fOnfileObject = nullptr;
152  Bool_t fOwnOnfileObject = kFALSE;
153  Int_t fOffset;
154  TIDs fIDs;
155  };
156 
157  // A 'node' in the list of StreamerElement ID, either
158  // the index of the element in the current streamerInfo
159  // or a set of unfolded/extracted StreamerElement for a sub-object.
160  struct TIDNode {
161  TIDNode() = default;
162  TIDNode(Int_t id) : fElemID(id), fElement(nullptr), fInfo(nullptr) {}
163  TIDNode(TStreamerInfo *info, Int_t offset) : fElemID(-1), fElement(nullptr), fInfo(nullptr) {
164  fNestedIDs = std::make_unique<TNestedIDs>(info, offset);
165  }
166  Int_t fElemID = -1;
167  TStreamerElement *fElement = nullptr;
168  TStreamerInfo *fInfo = nullptr;
169  std::unique_ptr<TNestedIDs> fNestedIDs;
170  };
171 
172  typedef std::vector<TConfiguredAction> ActionContainer_t;
173  class TActionSequence : public TObject {
174  TActionSequence() {};
175  public:
176  struct SequencePtr;
177  using SequenceGetter_t = SequencePtr(*)(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass);
178 
179  TActionSequence(TVirtualStreamerInfo *info, UInt_t maxdata) : fStreamerInfo(info), fLoopConfig(0) { fActions.reserve(maxdata); };
180  ~TActionSequence() {
181  delete fLoopConfig;
182  }
183 
184  template <typename action_t>
185  void AddAction( action_t action, TConfiguration *conf ) {
186  fActions.push_back( TConfiguredAction(action, conf) );
187  }
188  void AddAction(const TConfiguredAction &action ) {
189  fActions.push_back( action );
190  }
191 
192  TVirtualStreamerInfo *fStreamerInfo; ///< StreamerInfo used to derive these actions.
193  TLoopConfiguration *fLoopConfig; ///< If this is a bundle of memberwise streaming action, this configures the looping
194  ActionContainer_t fActions;
195 
196  void AddToOffset(Int_t delta);
197  void SetMissing();
198 
199  TActionSequence *CreateCopy();
200  static TActionSequence *CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy);
201  static TActionSequence *CreateWriteMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy);
202  TActionSequence *CreateSubSequence(const std::vector<Int_t> &element_ids, size_t offset);
203 
204  TActionSequence *CreateSubSequence(const TIDs &element_ids, size_t offset, SequenceGetter_t create);
205  void AddToSubSequence(TActionSequence *sequence, const TIDs &element_ids, Int_t offset, SequenceGetter_t create);
206 
207  void Print(Option_t * = "") const;
208 
209  // Maybe owner unique_ptr
210  struct SequencePtr {
211  TStreamerInfoActions::TActionSequence *fSequence = nullptr;
212  Bool_t fOwner = kFALSE;
213 
214  SequencePtr() = default;
215 
216  SequencePtr(SequencePtr &&from) : fSequence(from.fSequence), fOwner(from.fOwner) {
217  from.fOwner = false;
218  }
219 
220  SequencePtr(TStreamerInfoActions::TActionSequence *sequence, Bool_t owner) : fSequence(sequence), fOwner(owner) {}
221 
222  ~SequencePtr() {
223  if (fOwner) delete fSequence;
224  }
225 
226  // Accessor to the pointee.
227  TStreamerInfoActions::TActionSequence &operator*() const {
228  return *fSequence;
229  }
230 
231  // Accessor to the pointee
232  TStreamerInfoActions::TActionSequence *operator->() const {
233  return fSequence;
234  }
235 
236  // Return true is the pointee is not nullptr.
237  operator bool() {
238  return fSequence != nullptr;
239  }
240  };
241 
242  // SequenceGetter_t implementations
243 
244  static SequencePtr ReadMemberWiseActionsCollectionGetter(TStreamerInfo *info, TVirtualCollectionProxy * /* collectionProxy */, TClass * /* originalClass */) {
245  auto seq = info->GetReadMemberWiseActions(kTRUE);
246  return {seq, kFALSE};
247  }
248  static SequencePtr ConversionReadMemberWiseActionsViaProxyGetter(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass *originalClass) {
249  auto seq = collectionProxy->GetConversionReadMemberWiseActions(originalClass, info->GetClassVersion());
250  return {seq, kFALSE};
251  }
252  static SequencePtr ReadMemberWiseActionsViaProxyGetter(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass * /* originalClass */) {
253  auto seq = collectionProxy->GetReadMemberWiseActions(info->GetClassVersion());
254  return {seq, kFALSE};
255  }
256  static SequencePtr ReadMemberWiseActionsCollectionCreator(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass * /* originalClass */) {
257  auto seq = TStreamerInfoActions::TActionSequence::CreateReadMemberWiseActions(info,*collectionProxy);
258  return {seq, kTRUE};
259  }
260  // Creator5() = Creator1;
261  static SequencePtr ReadMemberWiseActionsGetter(TStreamerInfo *info, TVirtualCollectionProxy * /* collectionProxy */, TClass * /* originalClass */) {
262  auto seq = info->GetReadMemberWiseActions(kFALSE);
263  return {seq, kFALSE};
264  }
265 
266  static SequencePtr WriteMemberWiseActionsCollectionGetter(TStreamerInfo *info, TVirtualCollectionProxy * /* collectionProxy */, TClass * /* originalClass */) {
267  auto seq = info->GetWriteMemberWiseActions(kTRUE);
268  return {seq, kFALSE};
269  }
270  static SequencePtr WriteMemberWiseActionsViaProxyGetter(TStreamerInfo *, TVirtualCollectionProxy *collectionProxy, TClass * /* originalClass */) {
271  auto seq = collectionProxy->GetWriteMemberWiseActions();
272  return {seq, kFALSE};
273  }
274  static SequencePtr WriteMemberWiseActionsCollectionCreator(TStreamerInfo *info, TVirtualCollectionProxy *collectionProxy, TClass * /* originalClass */) {
275  auto seq = TStreamerInfoActions::TActionSequence::CreateWriteMemberWiseActions(info,*collectionProxy);
276  return {seq, kTRUE};
277  }
278  // Creator5() = Creator1;
279  static SequencePtr WriteMemberWiseActionsGetter(TStreamerInfo *info, TVirtualCollectionProxy * /* collectionProxy */, TClass * /* originalClass */) {
280  auto seq = info->GetWriteMemberWiseActions(kFALSE);
281  return {seq, kFALSE};
282  }
283  ClassDef(TActionSequence,0);
284  };
285 
286 }
287 
288 #endif // ROOT_TStreamerInfoActions
289 
290