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