ROOT  6.06/09
Reference Guide
TListOfDataMembers.cxx
Go to the documentation of this file.
1 // @(#)root/cont
2 // Author: Philippe Canal Aug 2013
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, 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 TListOfDataMembers
13 A collection of TDataMember objects designed for fast access given a
14 DeclId_t and for keep track of TDataMember that were described
15 unloaded data member.
16 */
17 
18 #include "TListOfDataMembers.h"
19 #include "TClass.h"
20 #include "TClassRef.h"
21 #include "TExMap.h"
22 #include "TDataMember.h"
23 #include "TGlobal.h"
24 #include "TInterpreter.h"
25 #include "TVirtualMutex.h"
26 #include "TError.h"
27 #include "TEnumConstant.h"
28 #include "TClassEdit.h"
29 
30 const unsigned int idsSize=19;
31 
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 /// Constructor.
36 
38  fClass(cl),fIds(0),fUnloaded(0),fIsLoaded(kFALSE), fLastLoadMarker(0)
39 {
40 }
41 
42 ////////////////////////////////////////////////////////////////////////////////
43 /// Destructor.
44 
46 {
48  delete fIds;
49  if (fUnloaded) fUnloaded->Delete();
50  delete fUnloaded;
51 }
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 /// Add a pair<id, object> to the map of data members and their ids.
55 
57 {
58  if (!fIds) fIds = new TExMap(idsSize);
59 
60  if (fClass) {
61  TDataMember *d = dynamic_cast<TDataMember*>(obj);
62  if (d) {
63  fIds->Add((Long64_t)d->GetDeclId(),(Long64_t)d);
64  }
65  } else {
66  TGlobal *g = dynamic_cast<TGlobal*>(obj);
67  if (g && g->GetDeclId()) {
68  fIds->Add((Long64_t)g->GetDeclId(),(Long64_t)g);
69  }
70  }
71 }
72 
73 ////////////////////////////////////////////////////////////////////////////////
74 /// Add object at the beginning of the list.
75 
77 {
79  MapObject(obj);
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Add object at the beginning of the list and also store option.
84 /// Storing an option is useful when one wants to change the behaviour
85 /// of an object a little without having to create a complete new
86 /// copy of the object. This feature is used, for example, by the Draw()
87 /// method. It allows the same object to be drawn in different ways.
88 
90 {
91  THashList::AddFirst(obj,opt);
92  MapObject(obj);
93 }
94 
95 ////////////////////////////////////////////////////////////////////////////////
96 /// Add object at the end of the list.
97 
99 {
100  THashList::AddLast(obj);
101  MapObject(obj);
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Add object at the end of the list and also store option.
106 /// Storing an option is useful when one wants to change the behaviour
107 /// of an object a little without having to create a complete new
108 /// copy of the object. This feature is used, for example, by the Draw()
109 /// method. It allows the same object to be drawn in different ways.
110 
112 {
113  THashList::AddLast(obj, opt);
114  MapObject(obj);
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// Insert object at location idx in the list.
119 
121 {
122  THashList::AddAt(obj, idx);
123  MapObject(obj);
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// Insert object after object after in the list.
128 
130 {
131  THashList::AddAfter(after, obj);
132  MapObject(obj);
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 /// Insert object after object after in the list.
137 
139 {
140  THashList::AddAfter(after, obj);
141  MapObject(obj);
142 }
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 /// Insert object before object before in the list.
146 
148 {
149  THashList::AddBefore(before, obj);
150  MapObject(obj);
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////
154 /// Insert object before object before in the list.
155 
157 {
158  THashList::AddBefore(before, obj);
159  MapObject(obj);
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Remove all objects from the list. Does not delete the objects unless
164 /// the THashList is the owner (set via SetOwner()).
165 
167 {
168  if (fUnloaded) fUnloaded->Clear(option);
169  if (fIds) fIds->Clear();
170  THashList::Clear(option);
171  fIsLoaded = kFALSE;
172 }
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 /// Delete all TDataMember object files.
176 
177 void TListOfDataMembers::Delete(Option_t *option /* ="" */)
178 {
179  if (fUnloaded) fUnloaded->Delete(option);
180  THashList::Delete(option);
181  fIsLoaded = kFALSE;
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Specialize FindObject to do search for the
186 /// a data member just by name or create it if its not already in the list
187 
189 {
191  if (!result) {
193  // We already have all the information, no need to search more
194  return 0;
195  }
196 
198 
200  if (fClass) decl = gInterpreter->GetDataMember(fClass->GetClassInfo(),name);
201  else decl = gInterpreter->GetDataMember(0,name);
202  if (decl) result = const_cast<TListOfDataMembers*>(this)->Get(decl);
203  }
204  return result;
205 }
206 
207 ////////////////////////////////////////////////////////////////////////////////
208 /// Return (after creating it if necessary) the TDataMember
209 /// describing the data member corresponding to the Decl 'id'.
210 
212 {
213  if (!id) return 0;
214 
215  return fIds ? (TDataMember*)fIds->GetValue((Long64_t)id) : 0;
216 }
217 
218 ////////////////////////////////////////////////////////////////////////////////
219 /// Return (after creating it if necessary) the TDataMember
220 /// describing the data member corresponding to the Decl 'id'.
221 
223 {
224  if (!id) return 0;
225 
226  TDictionary *dm = Find(id);
227  if (dm) return dm;
228 
229  if (fClass) {
231  // The interpreter does not know about this class yet (or a problem
232  // occurred that prevented the proper updating of fClassInfo).
233  // So this decl can not possibly be part of this class.
234  // [In addition calling GetClassInfo would trigger a late parsing
235  // of the header which we want to avoid].
236  return 0;
237  }
238  if (!gInterpreter->ClassInfo_Contains(fClass->GetClassInfo(),id)) return 0;
239  } else {
240  if (!gInterpreter->ClassInfo_Contains(0,id)) return 0;
241  }
242 
244 
245  DataMemberInfo_t *info = gInterpreter->DataMemberInfo_Factory(id,fClass ? fClass->GetClassInfo() : 0);
246 
247  // Let's see if this is a reload ...
248  const char *name = gInterpreter->DataMemberInfo_Name(info);
249 
251  if (update) {
252  if (fClass) {
253  ((TDataMember*)update)->Update(info);
254  } else {
255  ((TGlobal*)update)->Update(info);
256  }
257  dm = update;
258  }
259  if (!dm) {
260  if (fClass) dm = new TDataMember(info, fClass);
261  else dm = new TGlobal(info);
262  }
263  // Calling 'just' THahList::Add would turn around and call
264  // TListOfDataMembers::AddLast which should *also* do the fIds->Add.
265  THashList::AddLast(dm);
266  if (!fIds) fIds = new TExMap(idsSize);
267  fIds->Add((Long64_t)id,(Long64_t)dm);
268 
269  return dm;
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// Return (after creating it if necessary) the TDataMember
274 /// describing the data member corresponding to the Decl 'id'.
275 /// The skipChecks flag controls the consistency checks performed inspecting
276 /// the AST. In some cases, we explicitly alter the datamembers in the
277 /// typesystem with respect to the AST and therefore we must not enforce
278 /// consistency.
279 
280 TDictionary *TListOfDataMembers::Get(DataMemberInfo_t *info, bool skipChecks)
281 {
282  if (!info) return 0;
283 
284  TDictionary::DeclId_t id = gInterpreter->GetDeclId(info);
285  R__ASSERT( id != 0 && "DeclId should not be null");
286  TDictionary *dm = fIds ? (TDataMember*)fIds->GetValue((Long64_t)id) : 0;
287  if (!dm) {
288  if (fClass) {
290  // The interpreter does not know about this class yet (or a problem
291  // occurred that prevented the proper updating of fClassInfo).
292  // So this decl can not possibly be part of this class.
293  // [In addition calling GetClassInfo would trigger a late parsing
294  // of the header which we want to avoid].
295  return 0;
296  }
297  if (!skipChecks && !gInterpreter->ClassInfo_Contains(fClass->GetClassInfo(),id)) return 0;
298  } else {
299  if (!skipChecks && !gInterpreter->ClassInfo_Contains(0,id)) return 0;
300  }
301 
303 
304  DataMemberInfo_t *dm_info = gInterpreter->DataMemberInfo_FactoryCopy(info);
305 
306  // Let's see if this is a reload ...
307  const char *name = gInterpreter->DataMemberInfo_Name(info);
309  if (update) {
310  update->Update(dm_info);
311  dm = update;
312  }
313  if (!dm) {
314  if (fClass) dm = new TDataMember(dm_info, fClass);
315  else dm = new TGlobal(dm_info);
316  }
317  // Calling 'just' THahList::Add would turn around and call
318  // TListOfDataMembers::AddLast which should *also* do the fIds->Add.
319  THashList::AddLast(dm);
320  if (!fIds) fIds = new TExMap(idsSize);
321  fIds->Add((Long64_t)id,(Long64_t)dm);
322  }
323  return dm;
324 }
325 
326 ////////////////////////////////////////////////////////////////////////////////
327 /// Remove a pair<id, object> from the map of data members and their ids.
328 
330 {
331  if (!fIds) return;
332  if (fClass) {
333  TDataMember *d = dynamic_cast<TDataMember*>(obj);
334  if (d) {
335  if (d->GetDeclId()) {
336  fIds->Remove((Long64_t)d->GetDeclId());
337  }
338  d->Update(0);
339  }
340  } else {
341  TGlobal *g = dynamic_cast<TGlobal*>(obj);
342  if (g) {
343  if (g->GetDeclId()) {
344  fIds->Remove((Long64_t)g->GetDeclId());
345  }
346  g->Update(0);
347  }
348  }
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////////
352 /// Remove object from this collection and recursively remove the object
353 /// from all other objects (and collections).
354 /// This function overrides TCollection::RecursiveRemove that calls
355 /// the Remove function. THashList::Remove cannot be called because
356 /// it uses the hash value of the hash table. This hash value
357 /// is not available anymore when RecursiveRemove is called from
358 /// the TObject destructor.
359 
361 {
362  if (!obj) return;
363 
366  UnmapObject(obj);
367 
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Remove object from the list.
372 
374 {
375  Bool_t found;
376 
377  found = THashList::Remove(obj);
378  if (!found && fUnloaded) {
379  found = fUnloaded->Remove(obj);
380  }
381  UnmapObject(obj);
382  if (found) return obj;
383  else return 0;
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Remove object via its objlink from the list.
388 
390 {
391  if (!lnk) return 0;
392 
393  TObject *obj = lnk->GetObject();
394 
395  THashList::Remove(lnk);
396  if (fUnloaded) fUnloaded->Remove(obj);
397 
398  UnmapObject(obj);
399  return obj;
400 }
401 
402 ////////////////////////////////////////////////////////////////////////////////
403 /// Load all the DataMembers known to the interpreter for the scope 'fClass'
404 /// into this collection.
405 
407 {
409  // Class and union are not extendable, if we already
410  // loaded all the data member there is no need to recheck
411  if (fIsLoaded) return;
412  }
413 
414  // This will provoke the parsing of the headers if need be.
415  if (fClass && fClass->GetClassInfo() == 0) return;
416 
418 
419  ULong64_t currentTransaction = gInterpreter->GetInterpreterStateMarker();
420  if (currentTransaction == fLastLoadMarker) {
421  return;
422  }
423  fLastLoadMarker = currentTransaction;
424 
425  // In the case of namespace, even if we have loaded before we need to
426  // load again in case there was new data member added.
427 
428  // Mark the list as loaded to avoid an infinite recursion in the case
429  // where we have a data member that is a variable size array. In that
430  // case TDataMember::Init needs to get/load the list to find the data
431  // member used as the array size.
432  fIsLoaded = kTRUE;
433 
434  ClassInfo_t *info;
435  if (fClass) info = fClass->GetClassInfo();
436  else info = gInterpreter->ClassInfo_Factory();
437 
438  // Treat the complex<float>, complex<double> in a special way, i.e. replacing
439  // the datamembers with the ones of _root_std_complex<T>
440  bool skipChecks = false;
441  if (fClass){
442  auto complexType = TClassEdit::GetComplexType(fClass->GetName());
443  switch(complexType) {
445  {
446  break;
447  }
449  {
450  skipChecks = true;
451  info = TClass::GetClass("_root_std_complex<float>")->GetClassInfo();
452  break;
453  }
455  {
456  skipChecks = true;
457  info = TClass::GetClass("_root_std_complex<double>")->GetClassInfo();
458  break;
459  }
461  {
462  skipChecks = true;
463  info = TClass::GetClass("_root_std_complex<int>")->GetClassInfo();
464  break;
465  }
467  {
468  skipChecks = true;
469  info = TClass::GetClass("_root_std_complex<long>")->GetClassInfo();
470  break;
471  }
472  }
473  }
474 
475  // Now we follow the ordinary pattern
476  DataMemberInfo_t *t = gInterpreter->DataMemberInfo_Factory(info);
477  while (gInterpreter->DataMemberInfo_Next(t)) {
478  if (gInterpreter->DataMemberInfo_IsValid(t)) {
479  // Get will check if there is already there or create a new one
480  // (or re-use a previously unloaded version).
481  Get(t,skipChecks);
482  }
483  }
484  gInterpreter->DataMemberInfo_Delete(t);
485  if (!fClass) gInterpreter->ClassInfo_Delete(info);
486 }
487 
488 ////////////////////////////////////////////////////////////////////////////////
489 /// Stream an object of class TListOfDataMembers.
490 
491 void TListOfDataMembers::Streamer(TBuffer &R__b)
492 {
493  if (R__b.IsReading()) {
495  fIsLoaded = kTRUE;
496  } else {
498  }
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 /// Move the member or data member to the expect set of list.
503 
505  if (fClass) {
506  TDataMember *d = dynamic_cast<TDataMember*>(member);
507  if (d) {
508  if (d->GetDeclId()) {
509  if (!fIds) fIds = new TExMap(idsSize);
510  fIds->Add((Long64_t)d->GetDeclId(),(Long64_t)d);
511  }
513  if (update) fUnloaded->Remove(update);
514 
515  if (! THashList::FindObject(d) ) {
516  // Calling 'just' THahList::Add would turn around and call
517  // TListOfDataMembers::AddLast which should *also* do the fIds->Add.
519  }
520  }
521  } else {
522  TGlobal *g = dynamic_cast<TGlobal*>(member);
523  if (g) {
524  if (g->GetDeclId()) {
525  if (!fIds) fIds = new TExMap(idsSize);
526  fIds->Add((Long64_t)g->GetDeclId(),(Long64_t)g);
527 
529  if (update) fUnloaded->Remove(update);
530 
531  if (! THashList::FindObject(g) ) {
532  // Calling 'just' THahList::Add would turn around and call
533  // TListOfDataMembers::AddLast which should *also* do the fIds->Add.
535  }
536  }
537  }
538  }
539 
540 
541 }
542 
543 ////////////////////////////////////////////////////////////////////////////////
544 /// Mark 'all func' as being unloaded.
545 /// After the unload, the data member can no longer be found directly,
546 /// until the decl can be found again in the interpreter (in which
547 /// the func object will be reused.
548 
550 {
551  TObjLink *lnk = FirstLink();
552  while (lnk) {
553  TDictionary *data = (TDictionary *)lnk->GetObject();
554  UnmapObject(data);
555  if (!fUnloaded) fUnloaded = new THashList;
556  fUnloaded->Add(data);
557 
558  lnk = lnk->Next();
559  }
560 
562  fIsLoaded = kFALSE;
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// Mark 'func' as being unloaded.
567 /// After the unload, the data member can no longer be found directly,
568 /// until the decl can be found again in the interpreter (in which
569 /// the func object will be reused.
570 
572 {
573  if (THashList::Remove(mem)) {
574  // We contains the object, let remove it from the other internal
575  // list and move it to the list of unloaded objects.
576 
577  UnmapObject(mem);
578  if (!fUnloaded) fUnloaded = new THashList;
579  fUnloaded->Add(mem);
580  }
581 }
virtual void Clear(Option_t *="")
Definition: TObject.h:110
void Add(ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table. The key should be unique.
Definition: TExMap.cxx:85
void AddFirst(TObject *obj)
Add object at the beginning of the list.
Definition: THashList.cxx:67
void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
A collection of TDataMember objects designed for fast access given a DeclId_t and for keep track of T...
void Remove(ULong64_t hash, Long64_t key)
Remove entry with specified key from the TExMap.
Definition: TExMap.cxx:214
void AddAt(TObject *obj, Int_t idx)
Insert object at location idx in the list.
virtual Int_t WriteClassBuffer(const TClass *cl, void *pointer)=0
void AddLast(TObject *obj)
Add object at the end of the list.
Definition: THashList.cxx:89
long long Long64_t
Definition: RtypesCore.h:69
Bool_t IsReading() const
Definition: TBuffer.h:81
TDictionary::DeclId_t DeclId_t
Definition: TInterpreter.h:236
const char Option_t
Definition: RtypesCore.h:62
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashList.cxx:212
THashList * fUnloaded
Map from DeclId_t to TDataMember*.
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:46
ULong64_t fLastLoadMarker
Mark whether Load was executed.
Long_t Property() const
Set TObject::fBits and fStreamerType to cache information about the class.
Definition: TClass.cxx:5652
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
const unsigned int idsSize
#define R__ASSERT(e)
Definition: TError.h:98
void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: THashList.cxx:183
int Int_t
Definition: RtypesCore.h:41
virtual void Clear(Option_t *option)
Remove all objects from the list.
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
#define gInterpreter
Definition: TInterpreter.h:502
void Load()
Load all the DataMembers known to the interpreter for the scope 'fClass' into this collection...
void AddLast(TObject *obj)
Add object at the end of the list.
void RecursiveRemove(TObject *obj)
Remove object from this collection and recursively remove the object from all other objects (and coll...
Definition: THashList.cxx:252
void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Bool_t IsLoaded() const
const void * DeclId_t
Definition: TDictionary.h:209
TDictionary * Find(DeclId_t id) const
Return (after creating it if necessary) the TDataMember describing the data member corresponding to t...
ClassImp(TListOfDataMembers) TListOfDataMembers
Constructor.
void UnmapObject(TObject *obj)
Remove a pair from the map of data members and their ids.
Bool_t HasInterpreterInfoInMemory() const
Definition: TClass.h:373
void Class()
Definition: Class.C:29
void AddAfter(const TObject *after, TObject *obj)
Insert object after object after in the list.
virtual DeclId_t GetDeclId() const
Definition: TGlobal.cxx:93
TClass * fClass
pointer to the foreign object
virtual bool Update(DataMemberInfo_t *info)
Update the TFunction to reflect the new info.
XFontStruct * id
Definition: TGX11.cxx:108
EComplexType GetComplexType(const char *)
Definition: TClassEdit.cxx:96
~TListOfDataMembers()
Destructor.
THashList(const THashList &)
void Clear(Option_t *option="")
Remove all objects from the list.
Definition: THashList.cxx:167
TExMap * fIds
Context of this list. Not owned.
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition: TExMap.cxx:171
void AddAt(TObject *obj, Int_t idx)
Insert object at location idx in the list.
Definition: THashList.cxx:147
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:162
void Update(TDictionary *member)
Move the member or data member to the expect set of list.
ClassInfo_t * GetClassInfo() const
Definition: TClass.h:391
TObject * Remove(TObject *obj)
Remove object from the list.
Definition: THashList.cxx:284
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
void AddAfter(const TObject *after, TObject *obj)
Insert object after object after in the list.
Definition: THashList.cxx:129
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
DeclId_t GetDeclId() const
Global variables class (global variables are obtained from CINT).
Definition: TGlobal.h:29
virtual TObjLink * FirstLink() const
Definition: TList.h:101
void MapObject(TObject *obj)
Add a pair to the map of data members and their ids.
virtual Int_t ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onfile_class=0)=0
TDictionary::DeclId_t DeclId_t
unsigned long long ULong64_t
Definition: RtypesCore.h:70
#define R__LOCKGUARD(mutex)
void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Definition: THashList.cxx:111
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:2881
virtual bool Update(DataMemberInfo_t *info)
Update the TFunction to reflect the new info.
Definition: TGlobal.cxx:160
virtual TObject * FindObject(const char *name) const
Specialize FindObject to do search for the a data member just by name or create it if its not already...
virtual void Delete(Option_t *option="")
Delete all TDataMember object files.
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
void Unload()
Mark 'all func' as being unloaded.
virtual void Add(TObject *obj)
Definition: TList.h:81
void AddFirst(TObject *obj)
Add object at the beginning of the list.
TObject * Remove(TObject *obj)
Remove object from the list.
double result[121]
Bool_t fIsLoaded
Holder of TDataMember for unloaded DataMembers.
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:35
TDictionary * Get(DeclId_t id)
Return (after creating it if necessary) the TDataMember describing the data member corresponding to t...