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