Logo ROOT   6.14/05
Reference Guide
TOutputListSelectorDataMap.cxx
Go to the documentation of this file.
1 // @(#)root/proofplayer:$Id$
2 // Author: Axel Naumann, 2010-06-09
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2010, 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 /** \class TOutputListSelectorDataMap
13 \ingroup proofkernel
14 
15 Set the selector's data members to the corresponding elements of the
16 output list.
17 
18 */
19 
21 
22 #include "TClass.h"
23 #include "TDataMember.h"
24 #include "TExMap.h"
25 #include "THashTable.h"
26 #include "TList.h"
27 #include "TMemberInspector.h"
28 #include "TProofDebug.h"
29 #include "TSelector.h"
30 
31 #include <cstddef>
32 
33 namespace {
34 
35  static TClass* IsSettableDataMember(TDataMember* dm) {
36  if (!dm || !dm->IsaPointer() || dm->IsBasic()) return 0;
37  TString dtTypeName = dm->GetFullTypeName();
38  if (!dtTypeName.EndsWith("*")) return 0;
39  dtTypeName.Remove(dtTypeName.Length()-1);
40  return TClass::GetClass(dtTypeName);
41  }
42 
43  class TSetSelDataMembers: public TMemberInspector {
44  public:
45  TSetSelDataMembers(const TOutputListSelectorDataMap& owner, TCollection* dmInfo, TList* output);
47  void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
48  Ssiz_t GetNumSet() const { return fNumSet; }
49  private:
50  TCollection* fDMInfo; // output list object name / member name pairs for output list entries
51  TList* fOutputList; // merged output list
52  Ssiz_t fNumSet; // number of initialized data members
53  const TOutputListSelectorDataMap& fOwner; // owner, used for messaging
54  };
55 }
56 
57 ////////////////////////////////////////////////////////////////////////////////
58 
59 TSetSelDataMembers::TSetSelDataMembers(const TOutputListSelectorDataMap& owner,
60  TCollection* dmInfo, TList* output):
61  fDMInfo(dmInfo), fOutputList(output), fNumSet(0), fOwner(owner)
62 {}
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// This method is called by the ShowMembers() method for each
66 /// data member to recursively collect all base classes' members.
67 ///
68 /// cl is the pointer to the current class
69 /// parent is the parent name (in case of composed objects)
70 /// name is the data member name
71 /// addr is the data member address
72 
73 void TSetSelDataMembers::Inspect(TClass *cl, const char* parent, const char *name, const void *addr, Bool_t /* isTransient */)
74 {
75  while (name[0] == '*') ++name;
76 
77  TObject* mapping = fDMInfo->FindObject(name);
78  if (!mapping) return;
79 
80  PDB(kOutput,1) fOwner.Info("SetDataMembers()",
81  "data member `%s%s::%s' maps to output list object `%s'",
82  cl->GetName(), parent, name, mapping->GetTitle());
83 
84  TObject* outputObj = fOutputList->FindObject(mapping->GetTitle());
85  if (!outputObj) {
86  PDB(kOutput,1) fOwner.Warning("SetDataMembers()",
87  "object `%s' not found in output list!",
88  mapping->GetTitle());
89  return;
90  }
91 
92  // Check data member type
93  TDataMember *dm = cl->GetDataMember(name);
94  TClass* cldt = IsSettableDataMember(dm);
95  if (!cldt) {
96  PDB(kOutput,1) fOwner.Warning("SetDataMembers()",
97  "unusable data member `%s' should have been detected by TCollectDataMembers!",
98  name);
99  return;
100  }
101 
102  char *pointer = (char*)addr;
103  char **ppointer = (char**)(pointer);
104  if (*ppointer) {
105  // member points to something - replace instead of delete to not crash on deleting uninitialized values.
106  fOwner.Warning("SetDataMembers()", "potential memory leak: replacing data member `%s' != 0. "
107  "Please initialize %s to 0 in constructor %s::%s()",
108  name, name, cl->GetName(), cl->GetName());
109  }
110  *ppointer = (char*)outputObj;
111  ++fNumSet;
112 }
113 
114 
115 namespace {
116  class TCollectDataMembers: public TMemberInspector {
117  public:
118  TCollectDataMembers(const TOutputListSelectorDataMap& owner): fOwner(owner) { }
119  ~TCollectDataMembers();
121  void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
122  TExMap& GetMemberPointers() { return fMap; }
123  private:
124  TExMap fMap; //map of data member's value to TDataMember
125  const TOutputListSelectorDataMap& fOwner; //owner, used for messaging
126  };
127 }
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 /// This method is called by the ShowMembers() method for each
131 /// data member to recursively collect all base classes' members.
132 ///
133 /// cl is the pointer to the current class
134 /// parent is the parent name (in case of composed objects)
135 /// name is the data member name
136 /// addr is the data member address
137 
138 void TCollectDataMembers::Inspect(TClass *cl, const char* /*parent*/, const char *name, const void *addr, Bool_t /* isTransient */)
139 {
140  TDataMember *dm = cl->GetDataMember(name);
141  if (!IsSettableDataMember(dm)) return;
142 
143  char *pointer = (char*)addr;
144  char **ppointer = (char**)(pointer);
145  char **p3pointer = (char**)(*ppointer);
146  if (p3pointer) {
147  // The data member points to something.
148  // Handle multiple pointers to the same output list object:
149  TObject* prev = (TObject*) (ptrdiff_t)fMap.GetValue((Long64_t)(ptrdiff_t)p3pointer);
150  if (prev) {
151  // We have a previous entry - is it a data member or already a TList (of data members)?
152  if (prev->InheritsFrom(TDataMember::Class())) {
153  fMap.Remove((Long64_t)(ptrdiff_t)p3pointer);
154  TList* dmList = new TList;
155  dmList->Add(prev);
156  dmList->Add(dm);
157  fMap.Add((Long64_t)(ptrdiff_t)p3pointer, (Long64_t)(ptrdiff_t)dmList);
158  } else {
159  TList* prevList = (TList*) prev;
160  prevList->Add(dm);
161  }
162  } else {
163  fMap.Add((Long64_t)(ptrdiff_t)p3pointer, (Long64_t)(ptrdiff_t)dm);
164  }
165  if (name[0] == '*') ++name;
166  PDB(kOutput,1) fOwner.Info("Init()", "considering data member `%s'", name);
167  }
168 }
169 
170 TCollectDataMembers::~TCollectDataMembers() {
171  // Destructor
172 
173  // Clean up collection of TDataMembers in fMap
174  TExMapIter iMembers(&fMap);
175  Long64_t key;
176  Long64_t value;
177  while (iMembers.Next(key, value)) {
178  TObject* obj = (TObject*) (ptrdiff_t) value;
179  if (obj->InheritsFrom(TList::Class())) {
180  delete obj;
181  }
182  }
183 }
184 
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Create a mapper between output list items and TSelector data members.
189 
191  fMap(0)
192 {
193  if (sel) Init(sel);
194 }
195 
196 ////////////////////////////////////////////////////////////////////////////////
197 /// Return static name for TOutputListSelectorDataMap objects.
198 
200 {
201  return "PROOF_TOutputListSelectorDataMap_object";
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Initialize the data member <-> output list mapping from a selector.
206 
208 {
209  if (!sel) {
210  PDB(kOutput,1) Warning("Init","Leave (no selector!)");
211  return kFALSE;
212  }
213  TCollection* outList = sel->GetOutputList();
214  if (!outList) {
215  PDB(kOutput,1) Info("Init()","Leave (no output)");
216  return kFALSE;
217  }
218 
219  if (outList->FindObject(GetName())) {
220  // mapping already exists?!
221  PDB(kOutput,1) Warning("Init","Mapping already exists!");
222  return kFALSE;
223  }
224 
225  if (fMap) delete fMap;
226  fMap = new THashTable;
227  fMap->SetOwner();
228 
229  TCollectDataMembers cdm(*this);
230  if (!sel->IsA()->CallShowMembers(sel, cdm)) {
231  // failed to map
232  PDB(kOutput,1) Warning("Init","Failed to determine mapping!");
233  return kFALSE;
234  }
235  PDB(kOutput,1) Info("Init()","Found %d data members.",
236  cdm.GetMemberPointers().GetSize());
237 
238  // Iterate over output list entries and find data members pointing to the
239  // same value. Store that mapping (or a miss).
240  TIter iOutput(outList);
241  TObject* output;
242  TList oneDM;
243  while ((output = iOutput())) {
244  TObject* obj = (TObject*) (ptrdiff_t)cdm.GetMemberPointers().GetValue((Long64_t)(ptrdiff_t)output);
245  if (!obj) continue;
246 
247  TList* addAllDM = 0;
248  if (obj->InheritsFrom(TDataMember::Class())) {
249  oneDM.Add(obj);
250  addAllDM = &oneDM;
251  } else {
252  addAllDM = (TList*) obj;
253  }
254  TIter iDM(addAllDM);
255  TDataMember* dm = 0;
256  while ((dm = (TDataMember*) iDM())) {
257  fMap->Add(new TNamed(dm->GetName(), output->GetName()));
258  PDB(kOutput,1) Info("Init()","Data member `%s' corresponds to output `%s'",
259  dm->GetName(), output->GetName());
260  }
261  oneDM.Clear();
262  }
263 
264  return kTRUE;
265 }
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Given an output list, set the data members of a TSelector.
269 
271 {
272  TList* output = sel->GetOutputList();
273  if (!output || output->IsEmpty()) return kTRUE;
274 
275  // Set fSelector's data members
276  TSetSelDataMembers ssdm(*this, fMap, output);
277  Bool_t res = sel->IsA()->CallShowMembers(sel, ssdm);
278  PDB(kOutput,1) Info("SetDataMembers()","%s, set %d data members.",
279  (res ? "success" : "failure"), ssdm.GetNumSet());
280  return res;
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Merge another TOutputListSelectorDataMap object, check
285 /// consistency.
286 
288 {
289  TOutputListSelectorDataMap* other = dynamic_cast<TOutputListSelectorDataMap*>(obj);
290  if (!other) return kFALSE;
291 
292  // check for consistency
293  TIter iMapping(other->GetMap());
294  TNamed* mapping = 0;
295  while ((mapping = (TNamed*)iMapping())) {
296  TObject* oldMap = fMap->FindObject(mapping->GetName());
297  if (!oldMap) {
298  fMap->Add(new TNamed(*mapping));
299  } else {
300  if (strcmp(oldMap->GetTitle(), mapping->GetTitle())) {
301  // ouch, contradicting maps!
302  PDB(kOutput,1)
303  Warning("Merge()",
304  "contradicting mapping for data member `%s' (output list entry `%s' vs. `%s'). "
305  "Cancelling automatic TSelector data member setting!",
306  mapping->GetName(), oldMap->GetTitle(), mapping->GetTitle());
307  fMap->Clear();
308  return kFALSE;
309  }
310  }
311  }
312  return kTRUE;
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// Find a TOutputListSelectorDataMap in a collection
317 
319 {
320  TIter iOutput(coll);
321  TObject* out = 0;
322  TOutputListSelectorDataMap* olsdm = 0;
323  while ((out = iOutput())) {
325  olsdm = dynamic_cast<TOutputListSelectorDataMap*>(out);
326  if (olsdm) break;
327  }
328  }
329  return olsdm;
330 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual void Clear(Option_t *option="")=0
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
long long Long64_t
Definition: RtypesCore.h:69
const char * GetFullTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
TOutputListSelectorDataMap(TSelector *sel=0)
Create a mapper between output list items and TSelector data members.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Bool_t Merge(TObject *obj)
Merge another TOutputListSelectorDataMap object, check consistency.
Basic string class.
Definition: TString.h:131
bool Bool_t
Definition: RtypesCore.h:59
Abstract base class for accessing the data-members of a class.
Bool_t Init(TSelector *sel)
Initialize the data member <-> output list mapping from a selector.
static TOutputListSelectorDataMap * FindInList(TCollection *coll)
Find a TOutputListSelectorDataMap in a collection.
Bool_t IsBasic() const
Return true if data member is a basic type, e.g. char, int, long...
THashTable implements a hash table to store TObject&#39;s.
Definition: THashTable.h:35
#define PDB(mask, level)
Definition: TProofDebug.h:56
void Class()
Definition: Class.C:29
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
void Init(TClassEdit::TInterpreterLookupHelper *helper)
Definition: TClassEdit.cxx:121
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
Bool_t SetDataMembers(TSelector *sel) const
Given an output list, set the data members of a TSelector.
A doubly linked list.
Definition: TList.h:44
virtual TObject * FindObject(const char *name) const
Must be redefined in derived classes.
Definition: TObject.cxx:321
const char * GetName() const
Return static name for TOutputListSelectorDataMap objects.
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Inspect() const
Dump contents of this object in a graphics canvas.
Definition: TObject.cxx:464
Collection abstract base class.
Definition: TCollection.h:63
Ssiz_t Length() const
Definition: TString.h:405
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
const Bool_t kFALSE
Definition: RtypesCore.h:88
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
int Ssiz_t
Definition: RtypesCore.h:63
virtual Bool_t IsEmpty() const
Definition: TCollection.h:186
#define ClassImp(name)
Definition: Rtypes.h:359
Set the selector&#39;s data members to the corresponding elements of the output list. ...
static constexpr double s
virtual void Add(TObject *obj)=0
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2887
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:399
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr)
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
TDataMember * GetDataMember(const char *datamember) const
Return pointer to datamember object with name "datamember".
Definition: TClass.cxx:3280
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
A TSelector object is used by the TTree::Draw, TTree::Scan, TTree::Process to navigate in a TTree and...
Definition: TSelector.h:33
Bool_t IsaPointer() const
Return true if data member is a pointer.
const Bool_t kTRUE
Definition: RtypesCore.h:87
char name[80]
Definition: TGX11.cxx:109
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual TList * GetOutputList() const
Definition: TSelector.h:71