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