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