Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClassTable.cxx
Go to the documentation of this file.
1// @(#)root/cont:$Id$
2// Author: Fons Rademakers 11/08/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, 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 TClassTable
13\ingroup Containers
14This class registers for all classes their name, id and dictionary
15function in a hash table. Classes are automatically added by the
16ctor of a special init class when a global of this init class is
17initialized when the program starts (see the ClassDef macro).
18
19All functions in TClassTable are thread-safe.
20*/
21
22#include "TClassTable.h"
23
24#include "TClass.h"
25#include "TClassEdit.h"
26#include "TProtoClass.h"
27#include "TList.h"
28#include "TROOT.h"
29#include "TString.h"
30#include "TError.h"
31#include "TRegexp.h"
32
33#include "TObjString.h"
34#include "TMap.h"
35
36#include "TInterpreter.h"
37
38#include <map>
39#include <memory>
40#include <typeinfo>
41#include <cstdlib>
42#include <string>
43#include <mutex>
44#include <unordered_map>
45
46using namespace ROOT;
47
49
54std::atomic<UInt_t> TClassTable::fgTally;
58
59
60static std::mutex &GetClassTableMutex()
61{
62 static std::mutex sMutex;
63 return sMutex;
64}
65
66// RAII to first normalize the input classname (operation that
67// both requires the ROOT global lock and might call `TClassTable`
68// resursively) and then acquire a lock on `TClassTable` local
69// mutex.
71 std::string fNormalizedName;
72
73public:
79
81 {
83 return;
84
85 // The recorded name is normalized, let's make sure we convert the
86 // input accordingly. This operation will take the ROOT global lock
87 // and might call recursively `TClassTable`, so this must be done
88 // outside of the `TClassTable` critical section.
90
91 GetClassTableMutex().lock();
92 }
93
95 GetClassTableMutex().unlock();
96 }
97
98 const std::string &GetNormalizedName() const {
99 return fNormalizedName;
100 }
101};
102
103////////////////////////////////////////////////////////////////////////////////
104
105namespace ROOT {
106 class TClassRec {
107 public:
109 fName(nullptr), fId(0), fDict(nullptr), fInfo(nullptr), fProto(nullptr), fNext(next)
110 {}
111
113 // TClassTable::fgIdMap->Remove(r->fInfo->name());
114 delete [] fName;
115 delete fProto;
116 delete fNext;
117 }
118
119 char *fName;
123 const std::type_info *fInfo;
126 };
127
128 class TClassAlt {
129 public:
130 TClassAlt(const char*alternate, const char *normName, TClassAlt *next) :
132 {}
133
135 // Nothing more to delete.
136 }
137
138 const char *fName; // Do not own
139 const char *fNormName; // Do not own
140 std::unique_ptr<TClassAlt> fNext;
141 };
142
143#define R__USE_STD_MAP
145#if defined R__USE_STD_MAP
146 // This wrapper class allow to avoid putting #include <map> in the
147 // TROOT.h header file.
148 public:
149 typedef std::map<std::string, TClassRec*> IdMap_t;
153#ifdef R__WIN32
154 // Window's std::map does NOT defined mapped_type
155 typedef TClassRec* mapped_type;
156#else
158#endif
159
160 private:
162
163 public:
164 void Add(const key_type &key, mapped_type &obj) {
165 fMap[key] = obj;
166 }
167
168 mapped_type Find(const key_type &key) const {
169 IdMap_t::const_iterator iter = fMap.find(key);
170 mapped_type cl = nullptr;
171 if (iter != fMap.end()) cl = iter->second;
172 return cl;
173 }
174
175 void Remove(const key_type &key) { fMap.erase(key); }
176
177 void Print() {
178 Info("TMapTypeToClassRec::Print", "printing the typeinfo map in TClassTable");
179 for (const_iterator iter = fMap.begin(); iter != fMap.end(); ++iter) {
180 printf("Key: %40s 0x%zx\n", iter->first.c_str(), (size_t)iter->second);
181 }
182 }
183#else
184 private:
185 TMap fMap;
186 public:
187#ifdef R__COMPLETE_MEM_TERMINATION
189 TIter next(&fMap);
190 TObjString *key;
191 while((key = (TObjString*)next())) {
192 delete key;
193 }
194 }
195#endif
196
197 void Add(const char *key, TClassRec *&obj)
198 {
199 // Add <key,value> pair to the map.
200
201 TObjString *realkey = new TObjString(key);
202 fMap.Add(realkey, (TObject*)obj);
203 }
204
205 TClassRec *Find(const char *key) const {
206 // Find the value corresponding the key.
207 const TPair *a = (const TPair *)fMap.FindObject(key);
208 if (a) return (TClassRec*) a->Value();
209 return 0;
210 }
211
212 void Remove(const char *key) {
213 // Remove the value corresponding the key.
214 TObjString realkey(key);
215 TObject *actual = fMap.Remove(&realkey);
216 delete actual;
217 }
218
219 void Print() {
220 // Print the content of the map.
221 Info("TMapTypeToClassRec::Print", "printing the typeinfo map in TClassTable");
222 TIter next(&fMap);
223 TObjString *key;
224 while((key = (TObjString*)next())) {
225 printf("Key: %s\n",key->String().Data());
226 TClassRec *data = (TClassRec*)fMap.GetValue(key);
227 if (data) {
228 printf(" class: %s %d\n",data->fName,data->fId);
229 } else {
230 printf(" no class: \n");
231 }
232 }
233 }
234#endif
235 };
236
237 static UInt_t ClassTableHash(const char *name, UInt_t size)
238 {
239 auto p = reinterpret_cast<const unsigned char*>( name );
240 UInt_t slot = 0;
241
242 while (*p) slot = slot<<1 ^ *p++;
243 slot %= size;
244
245 return slot;
246 }
247
248 std::vector<std::unique_ptr<TClassRec>> &GetDelayedAddClass()
249 {
250 static std::vector<std::unique_ptr<TClassRec>> delayedAddClass;
251 return delayedAddClass;
252 }
253
254 std::vector<std::pair<const char *, const char *>> &GetDelayedAddClassAlternate()
255 {
256 static std::vector<std::pair<const char *, const char *>> delayedAddClassAlternate;
258 }
259}
260
261std::unordered_map<ROOT::TClassRec *, std::vector<ROOT::TClassAlt *>> &GetClassRecToAltMap()
262{
263 static std::unordered_map<ROOT::TClassRec *, std::vector<ROOT::TClassAlt *>> classRecToAltMap;
264 return classRecToAltMap;
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// TClassTable is a singleton (i.e. only one can exist per application).
269
271{
272 if (gClassTable) return;
273
274 fgSize = 1009; //this is the result of (int)TMath::NextPrime(1000);
275 fgTable = new TClassRec* [fgSize];
277 fgIdMap = new IdMap_t;
278 memset(fgTable, 0, fgSize * sizeof(TClassRec*));
279 memset(fgAlternate, 0, fgSize * sizeof(TClassAlt *));
280 gClassTable = this;
281
282 for (auto &&r : GetDelayedAddClass()) {
283 AddClass(r->fName, r->fId, *r->fInfo, r->fDict, r->fBits);
284 };
285 GetDelayedAddClass().clear();
286
287 for (auto &&r : GetDelayedAddClassAlternate()) {
288 AddAlternate(r.first, r.second);
289 }
291}
292
293////////////////////////////////////////////////////////////////////////////////
294/// TClassTable singleton is deleted in Terminate().
295
297{
298 // Try to avoid spurious warning from memory leak checkers.
299 if (gClassTable != this) return;
300
301 for (UInt_t i = 0; i < fgSize; i++) {
302 delete fgTable[i]; // Will delete all the elements in the chain.
303 }
304 delete [] fgTable; fgTable = nullptr;
305 delete [] fgSortedTable; fgSortedTable = nullptr;
306 delete fgIdMap; fgIdMap = nullptr;
307}
308
309////////////////////////////////////////////////////////////////////////////////
310/// Return true fs the table exist.
311/// If the table does not exist but the delayed list does, then
312/// create the table and return true.
313
315{
316 // This will be set at the lastest during TROOT construction, so before
317 // any threading could happen.
318 if (!gClassTable || !fgTable) {
319 if (GetDelayedAddClass().size()) {
320 new TClassTable;
321 return kTRUE;
322 }
323 return kFALSE;
324 }
325 return kTRUE;
326}
327
328////////////////////////////////////////////////////////////////////////////////
329/// Print the class table. Before printing the table is sorted
330/// alphabetically. Only classes specified in option are listed.
331/// The default is to list all classes.
332/// Standard wildcarding notation supported.
333
334void TClassTable::Print(Option_t *option) const
335{
336 std::lock_guard<std::mutex> lock(GetClassTableMutex());
337
338 // This is the very rare case (i.e. called before any dictionary load)
339 // so we don't need to execute this outside of the critical section.
340 if (fgTally == 0 || !fgTable)
341 return;
342
343 SortTable();
344
345 int n = 0, ninit = 0, nl = 0;
346
347 if (!option) option = "";
348 int nch = strlen(option);
349 TRegexp re(option, kTRUE);
350
351 Printf("\nDefined classes");
352 Printf("class version bits initialized");
353 Printf("================================================================");
354 for (UInt_t i = 0; i < fgTally; i++) {
356 if (!r) break;
357 n++;
358 TString s = r->fName;
359 if (nch && strcmp(option,r->fName) && s.Index(re) == kNPOS) continue;
360 nl++;
361 if (TClass::GetClass(r->fName, kFALSE)) {
362 ninit++;
363 Printf("%-35s %6d %7d Yes", r->fName, r->fId, r->fBits);
364 } else
365 Printf("%-35s %6d %7d No", r->fName, r->fId, r->fBits);
366 }
367 Printf("----------------------------------------------------------------");
368 Printf("Listed Classes: %4d Total classes: %4d initialized: %4d",nl, n, ninit);
369 Printf("================================================================\n");
370}
371
372//---- static members --------------------------------------------------------
373
374////////////////////////////////////////////////////////////////////////////////
375/// Returns class at index from sorted class table. Don't use this iterator
376/// while modifying the class table. The class table can be modified
377/// when making calls like TClass::GetClass(), etc.
378/// Returns 0 if index points beyond last class name.
379
381{
382 if (index < fgTally) {
383 std::lock_guard<std::mutex> lock(GetClassTableMutex());
384
385 SortTable();
387 if (r)
388 return r->fName;
389 }
390 return nullptr;
391}
392
393//______________________________________________________________________________
395//______________________________________________________________________________
397
398namespace ROOT { class TForNamespace {}; } // Dummy class to give a typeid to namespace (see also TGenericClassInfo)
399
400////////////////////////////////////////////////////////////////////////////////
401/// Add a class to the class table (this is a static function).
402/// Note that the given cname *must* be already normalized.
403
404void TClassTable::Add(const char *cname, Version_t id, const std::type_info &info,
406{
407 if (!cname || *cname == 0)
408 ::Fatal("TClassTable::Add()", "Failed to deduce type for '%s'", info.name());
409
410 // This will be set at the lastest during TROOT construction, so before
411 // any threading could happen.
412 if (!gClassTable)
413 new TClassTable;
414
415 std::unique_lock<std::mutex> lock(GetClassTableMutex());
416
417 // check if already in table, if so return
419 if (r->fName && r->fInfo) {
420 if ( strcmp(r->fInfo->name(), typeid(ROOT::TForNamespace).name()) ==0
421 && strcmp(info.name(), typeid(ROOT::TForNamespace).name()) ==0 ) {
422 // We have a namespace being reloaded.
423 // This okay we just keep the old one.
424 return;
425 }
427 lock.unlock(); // Warning might recursively call TClassTable during gROOT init
428 // Warn only for class that are not STD classes
429 ::Warning("TClassTable::Add", "class %s already in TClassTable", cname);
430 }
431 return;
432 } else if (ROOT::Internal::gROOTLocal && gCling) {
433 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
434 if (oldcl) { // && oldcl->GetClassInfo()) {
435 // As a work-around to ROOT-6012, we need to register the class even if
436 // it is not a template instance, because a forward declaration in the header
437 // files loaded by the current dictionary wil also de-activate the update
438 // class info mechanism!
439
440 // The TClass exist and already has a class info, so it must
441 // correspond to a class template instantiation which the interpreter
442 // was able to make with the library containing the TClass Init.
443 // Because it is already known to the interpreter, the update class info
444 // will not be triggered, we need to force it.
446 }
447 }
448
449 if (!r->fName)
450 r->fName = StrDup(cname);
451 r->fId = id;
452 r->fBits = pragmabits;
453 r->fDict = dict;
454 r->fInfo = &info;
455
456 fgIdMap->Add(info.name(),r);
457
459}
460
461////////////////////////////////////////////////////////////////////////////////
462/// Add a class to the class table (this is a static function).
463/// The caller of this function should be holding the ROOT Write lock.
464
466{
467 // This will be set at the lastest during TROOT construction, so before
468 // any threading could happen.
469 if (!gClassTable)
470 new TClassTable;
471
472 std::unique_lock<std::mutex> lock(GetClassTableMutex());
473
474 // By definition the name in the TProtoClass is (must be) the normalized
475 // name, so there is no need to tweak it.
476 const char *cname = proto->GetName();
477
478 // check if already in table, if so return
480 if (r->fName) {
481 if (r->fProto) delete r->fProto;
482 r->fProto = proto;
483 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
484
485 lock.unlock(); // FillTClass might recursively call TClassTable during gROOT init
486 if (oldcl && oldcl->GetState() == TClass::kHasTClassInit)
487 proto->FillTClass(oldcl);
488 return;
489 } else if (ROOT::Internal::gROOTLocal && gCling) {
490 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
491 if (oldcl) { // && oldcl->GetClassInfo()) {
492 // As a work-around to ROOT-6012, we need to register the class even if
493 // it is not a template instance, because a forward declaration in the header
494 // files loaded by the current dictionary wil also de-activate the update
495 // class info mechanism!
496
497 lock.unlock(); // Warning might recursively call TClassTable during gROOT init
498 ::Warning("TClassTable::Add(TProtoClass*)","Called for existing class without a prior call add the dictionary function.");
499 }
500 }
501
502 r->fName = StrDup(cname);
503 r->fId = 0;
504 r->fBits = 0;
505 r->fDict = nullptr;
506 r->fInfo = nullptr;
507 r->fProto= proto;
508
510}
511
512////////////////////////////////////////////////////////////////////////////////
513
515{
516 // This will be set at the lastest during TROOT construction, so before
517 // any threading could happen.
518 if (!gClassTable)
519 new TClassTable;
520
521 std::lock_guard<std::mutex> lock(GetClassTableMutex());
522
524
525 for (const TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
526 if (strcmp(alternate,a->fName)==0) {
527 if (strcmp(normName,a->fNormName) != 0) {
528 fprintf(stderr,"Error in TClassTable::AddAlternate: "
529 "Second registration of %s with a different normalized name (old: '%s', new: '%s')\n",
530 alternate, a->fNormName, normName);
531 }
532 return nullptr;
533 }
534 }
535
537
539 if (fgTable[slotNorm]) {
541 // Let others connect a class record to its class alternative names
542 if (auto it = classToAlt.find(fgTable[slotNorm]); it == classToAlt.end())
543 classToAlt[fgTable[slotNorm]] = std::vector<ROOT::TClassAlt *>{fgAlternate[slot]};
544 else
546 }
547
548 return fgAlternate[slot];
549}
550
551////////////////////////////////////////////////////////////////////////////////
552///
554{
555 if (!alt || !gClassTable)
556 return;
557
558 std::lock_guard<std::mutex> lock(GetClassTableMutex());
559
561
562 if (!fgAlternate[slot])
563 return;
564
565 if (fgAlternate[slot] == alt)
566 fgAlternate[slot] = alt->fNext.release();
567 else {
568 for (TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
569 if (a->fNext.get() == alt) {
570 a->fNext.swap( alt->fNext );
571 assert( alt == alt->fNext.get());
572 alt->fNext.release();
573 }
574 }
575 }
576 delete alt;
577}
578
579////////////////////////////////////////////////////////////////////////////////
580
581Bool_t TClassTable::Check(const char *cname, std::string &normname)
582{
583 if (!CheckClassTableInit())
584 return kFALSE;
585
586 std::lock_guard<std::mutex> lock(GetClassTableMutex());
587
589
590 // Check if 'cname' is a known normalized name.
591 for (TClassRec *r = fgTable[slot]; r; r = r->fNext)
592 if (strcmp(cname,r->fName)==0) return kTRUE;
593
594 // See if 'cname' is register in the list of alternate names
595 for (const TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
596 if (strcmp(cname,a->fName)==0) {
597 normname = a->fNormName;
598 return kTRUE;
599 }
600 }
601
602 return kFALSE;
603}
604
605////////////////////////////////////////////////////////////////////////////////
606/// Remove a class from the class table. This happens when a shared library
607/// is unloaded (i.e. the dtor's of the global init objects are called).
608
609void TClassTable::Remove(const char *cname)
610{
611 if (!CheckClassTableInit())
612 return;
613
614 std::lock_guard<std::mutex> lock(GetClassTableMutex());
615
617
618 TClassRec *r;
619 TClassRec *prev = nullptr;
620 for (r = fgTable[slot]; r; r = r->fNext) {
621 if (!strcmp(r->fName, cname)) {
622 if (prev)
623 prev->fNext = r->fNext;
624 else
625 fgTable[slot] = r->fNext;
626 fgIdMap->Remove(r->fInfo->name());
627 r->fNext = nullptr; // Do not delete the others.
628 delete r;
629 fgTally--;
631 break;
632 }
633 prev = r;
634 }
635}
636
637////////////////////////////////////////////////////////////////////////////////
638/// Find a class by name in the class table (using hash of name). Returns
639/// 0 if the class is not in the table. Unless arguments insert is true in
640/// which case a new entry is created and returned.
641/// `cname` must be the normalized name of the class.
642
644{
645 // Internal routine, no explicit lock needed here.
646
648
649 for (TClassRec *r = fgTable[slot]; r; r = r->fNext)
650 if (strcmp(cname, r->fName) == 0)
651 return r;
652
653 if (!insert)
654 return nullptr;
655
657
658 fgTally++;
659 return fgTable[slot];
660}
661
662////////////////////////////////////////////////////////////////////////////////
663/// Returns the ID of a class.
664
666{
668
669 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
670 if (r)
671 return r->fId;
672 return -1;
673}
674
675////////////////////////////////////////////////////////////////////////////////
676/// Returns the pragma bits as specified in the LinkDef.h file.
677
679{
681
682 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
683 if (r)
684 return r->fBits;
685 return 0;
686}
687
688////////////////////////////////////////////////////////////////////////////////
689/// Given the class name returns the Dictionary() function of a class
690/// (uses hash of name).
691
693{
694 if (gDebug > 9) {
695 ::Info("GetDict", "searches for %s", cname);
696 fgIdMap->Print();
697 }
699
700 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
701 if (r)
702 return r->fDict;
703 return nullptr;
704}
705
706////////////////////////////////////////////////////////////////////////////////
707/// Given the std::type_info returns the Dictionary() function of a class
708/// (uses hash of std::type_info::name()).
709
711{
712 if (!CheckClassTableInit())
713 return nullptr;
714
715 if (gDebug > 9)
716 ROOT::GetROOT(); // Info might recursively call TClassTable during the gROOT init
717
718 std::lock_guard<std::mutex> lock(GetClassTableMutex());
719
720 if (gDebug > 9) {
721 ::Info("GetDict", "searches for %s at 0x%zx", info.name(), (size_t)&info);
722 fgIdMap->Print();
723 }
724
725 TClassRec *r = fgIdMap->Find(info.name());
726 if (r)
727 return r->fDict;
728 return nullptr;
729}
730
731////////////////////////////////////////////////////////////////////////////////
732/// Given the normalized class name returns the Dictionary() function of a class
733/// (uses hash of name).
734
736{
737 if (!CheckClassTableInit())
738 return nullptr;
739
740 if (gDebug > 9)
741 ROOT::GetROOT(); // Info might recursively call TClassTable during the gROOT init
742
743 std::lock_guard<std::mutex> lock(GetClassTableMutex());
744
745 if (gDebug > 9) {
746 ::Info("GetDict", "searches for %s", cname);
747 fgIdMap->Print();
748 }
749
751 if (r)
752 return r->fDict;
753 return nullptr;
754}
755
756////////////////////////////////////////////////////////////////////////////////
757/// Given the class name returns the TClassProto object for the class.
758/// (uses hash of name).
759
761{
762 if (gDebug > 9) {
763 ::Info("GetDict", "searches for %s", cname);
764 }
765
766 if (!CheckClassTableInit())
767 return nullptr;
768
770
771 if (gDebug > 9) {
772 // Because of the early call to Info, gROOT is already initialized
773 // and thus this will not cause a recursive call to TClassTable.
774 ::Info("GetDict", "searches for %s", cname);
775 fgIdMap->Print();
776 }
777
778 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
779 if (r)
780 return r->fProto;
781 return nullptr;
782}
783
784////////////////////////////////////////////////////////////////////////////////
785/// Given the class normalized name returns the TClassProto object for the class.
786/// (uses hash of name).
787
789{
790 if (gDebug > 9) {
791 ::Info("GetDict", "searches for %s", cname);
792 }
793
794 if (!CheckClassTableInit())
795 return nullptr;
796
797 std::lock_guard<std::mutex> lock(GetClassTableMutex());
798
799 if (gDebug > 9) {
800 fgIdMap->Print();
801 }
802
804 if (r)
805 return r->fProto;
806 return nullptr;
807}
808
809////////////////////////////////////////////////////////////////////////////////
810
811extern "C" {
812 static int ClassComp(const void *a, const void *b)
813 {
814 // Function used for sorting classes alphabetically.
815
816 return strcmp((*(TClassRec **)a)->fName, (*(TClassRec **)b)->fName);
817 }
818}
819
820////////////////////////////////////////////////////////////////////////////////
821/// Returns next class from sorted class table. Don't use this iterator
822/// while modifying the class table. The class table can be modified
823/// when making calls like TClass::GetClass(), etc.
824
826{
827 std::lock_guard<std::mutex> lock(GetClassTableMutex());
828
829 if (fgCursor < fgTally) {
831 return r->fName;
832 }
833
834 return nullptr;
835}
836
837////////////////////////////////////////////////////////////////////////////////
838/// Print the class table. Before printing the table is sorted
839/// alphabetically.
840
842{
843 if (fgTally == 0 || !fgTable)
844 return;
845
846 std::lock_guard<std::mutex> lock(GetClassTableMutex());
847
848 SortTable();
849
850 int n = 0, ninit = 0;
851
852 Printf("\nDefined classes");
853 Printf("class version bits initialized");
854 Printf("================================================================");
855 UInt_t last = fgTally;
856 for (UInt_t i = 0; i < last; i++) {
858 if (!r) break;
859 n++;
860 // Do not use TClass::GetClass to avoid any risk of autoloading.
861 if (gROOT->GetListOfClasses()->FindObject(r->fName)) {
862 ninit++;
863 Printf("%-35s %6d %7d Yes", r->fName, r->fId, r->fBits);
864 } else
865 Printf("%-35s %6d %7d No", r->fName, r->fId, r->fBits);
866 }
867 Printf("----------------------------------------------------------------");
868 Printf("Total classes: %4d initialized: %4d", n, ninit);
869 Printf("================================================================\n");
870}
871
872////////////////////////////////////////////////////////////////////////////////
873/// Sort the class table by ascending class ID's.
874
876{
877 // Internal routine.
878
879 if (!fgSorted) {
880 delete [] fgSortedTable;
882
883 int j = 0;
884 for (UInt_t i = 0; i < fgSize; i++)
885 for (TClassRec *r = fgTable[i]; r; r = r->fNext)
886 fgSortedTable[j++] = r;
887
889 fgSorted = kTRUE;
890 }
891}
892
893////////////////////////////////////////////////////////////////////////////////
894/// Deletes the class table (this static class function calls the dtor).
895
897{
898 if (gClassTable) {
899 for (UInt_t i = 0; i < fgSize; i++)
900 delete fgTable[i]; // Will delete all the elements in the chain.
901
902 delete [] fgTable; fgTable = nullptr;
903 delete [] fgSortedTable; fgSortedTable = nullptr;
904 delete fgIdMap; fgIdMap = nullptr;
905 fgSize = 0;
907 }
908}
909
910////////////////////////////////////////////////////////////////////////////////
911/// Global function called by the ctor of a class's init class
912/// (see the ClassDef macro).
913
914void ROOT::AddClass(const char *cname, Version_t id,
915 const std::type_info& info,
916 DictFuncPtr_t dict,
918{
919 if (!TROOT::Initialized() && !gClassTable) {
920 auto r = std::unique_ptr<TClassRec>(new TClassRec(nullptr));
921 r->fName = StrDup(cname);
922 r->fId = id;
923 r->fBits = pragmabits;
924 r->fDict = dict;
925 r->fInfo = &info;
926 GetDelayedAddClass().emplace_back(std::move(r));
927 } else {
929 }
930}
931
932////////////////////////////////////////////////////////////////////////////////
933/// Global function called by GenerateInitInstance.
934/// (see the ClassDef macro).
935
937{
938 if (!TROOT::Initialized() && !gClassTable) {
940 // If a library is loaded before gROOT is initialized we can assume
941 // it is hard linked along side libCore (or is libCore) thus can't
942 // really be unloaded.
943 return nullptr;
944 } else {
946 }
947}
948
950{
951 // This routine is meant to be called (indirectly) by dlclose so we
952 // we are guaranteed that the library initialization has completed.
954}
955
956////////////////////////////////////////////////////////////////////////////////
957/// Global function to update the version number.
958/// This is called via the RootClassVersion macro.
959///
960/// if cl!=0 and cname==-1, set the new class version if and only is
961/// greater than the existing one and greater or equal to 2;
962/// and also ignore the request if fVersionUsed is true.
963///
964/// Note on class version number:
965/// - If no class has been specified, TClass::GetVersion will return -1
966/// - The Class Version 0 request the whole object to be transient
967/// - The Class Version 1, unless specify via ClassDef indicates that the
968/// I/O should use the TClass checksum to distinguish the layout of the class
970{
971 if (cname && cname != (void*)-1 && TClassTable::CheckClassTableInit()) {
974 if (r)
975 r->fId = newid;
976 }
977 if (cl) {
978 if (cl->fVersionUsed) {
979 // Problem, the reset is called after the first usage!
980 if (cname!=(void*)-1)
981 Error("ResetClassVersion","Version number of %s can not be changed after first usage!",
982 cl->GetName());
983 } else {
984 if (newid < 0) {
985 Error("SetClassVersion","The class version (for %s) must be positive (value %d is ignored)",cl->GetName(),newid);
986 }
987 if (cname==(void*)-1) {
988 if (cl->fClassVersion<newid && 2<=newid) {
990 }
991 } else {
993 }
994 }
995 }
996}
997
998////////////////////////////////////////////////////////////////////////////////
999/// Global function called by the dtor of a class's init class
1000/// (see the ClassDef macro).
1001/// The caller of this function should be holding the ROOT Write lock.
1002
1004{
1005 // don't delete class information since it is needed by the I/O system
1006 // to write the StreamerInfo to file
1007 if (cname) {
1008 // Let's still remove this information to allow reloading later.
1009 // Anyway since the shared library has been unloaded, the dictionary
1010 // pointer is now invalid ....
1011 // We still keep the TClass object around because TFile needs to
1012 // get to the TStreamerInfo.
1013 if (oldcl)
1014 oldcl->SetUnloaded();
1016 }
1017}
1018
1019////////////////////////////////////////////////////////////////////////////////
1020/// Global function to register the implementation file and line of
1021/// a class template (i.e. NOT a concrete class).
1022
1023TNamed *ROOT::RegisterClassTemplate(const char *name, const char *file,
1024 Int_t line)
1025{
1026 static TList table;
1027 static Bool_t isInit = []() {
1028 table.SetOwner(kTRUE);
1029 table.UseRWLock();
1030 return true;
1031 }();
1032 (void)isInit;
1033
1034 TString classname(name);
1035 Ssiz_t loc = classname.Index("<");
1036 if (loc >= 1)
1037 classname.Remove(loc);
1038 TNamed *reg = (TNamed*)table.FindObject(classname);
1039 if (file) {
1040 if (reg)
1041 reg->SetTitle(file);
1042 else {
1043 reg = new TNamed((const char*)classname, file);
1044 table.Add(reg);
1045 }
1046 reg->SetUniqueID(line);
1047 }
1048 return reg;
1049}
1050
1051std::vector<std::string> TClassTable::GetClassAlternativeNames(const char *cname)
1052{
1053 std::lock_guard<std::mutex> lock(GetClassTableMutex());
1054
1056 if (!fgTable[slot])
1057 return {};
1058 const auto &classRecToAltMap = GetClassRecToAltMap();
1059 if (auto it = classRecToAltMap.find(fgTable[slot]); it == classRecToAltMap.end())
1060 return {};
1061
1062 const auto &classAlts = classRecToAltMap.at(fgTable[slot]);
1063 std::vector<std::string> ret;
1064 ret.reserve(classAlts.size());
1065 for (const auto *classAlt : classAlts) {
1066 ret.push_back(classAlt->fName);
1067 }
1068
1069 return ret;
1070}
#define SafeDelete(p)
Definition RConfig.hxx:533
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:77
short Version_t
Class version identifier (short)
Definition RtypesCore.h:79
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:60
short Short_t
Signed Short integer 2 bytes (short)
Definition RtypesCore.h:53
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
constexpr Ssiz_t kNPOS
The equivalent of std::string::npos for the ROOT class TString.
Definition RtypesCore.h:131
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
TClass *(* DictFuncPtr_t)()
Definition Rtypes.h:86
static std::mutex & GetClassTableMutex()
TClassTable * gClassTable
static int ClassComp(const void *a, const void *b)
std::unordered_map< ROOT::TClassRec *, std::vector< ROOT::TClassAlt * > > & GetClassRecToAltMap()
R__EXTERN TClassTable * gClassTable
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:241
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char cname
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void reg
char name[80]
Definition TGX11.cxx:110
R__EXTERN TInterpreter * gCling
Int_t gDebug
Global variable setting the debug level. Set to 0 to disable, increase it in steps of 1 to increase t...
Definition TROOT.cxx:627
#define gROOT
Definition TROOT.h:411
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2509
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2563
const char * proto
Definition civetweb.c:18822
const_iterator end() const
const char * fName
TClassAlt(const char *alternate, const char *normName, TClassAlt *next)
std::unique_ptr< TClassAlt > fNext
const char * fNormName
DictFuncPtr_t fDict
TClassRec(TClassRec *next)
const std::type_info * fInfo
TClassRec * fNext
TProtoClass * fProto
IdMap_t::size_type size_type
IdMap_t::mapped_type mapped_type
void Add(const key_type &key, mapped_type &obj)
IdMap_t::key_type key_type
std::map< std::string, TClassRec * > IdMap_t
IdMap_t::const_iterator const_iterator
void Remove(const key_type &key)
mapped_type Find(const key_type &key) const
IdMap_t::size_type size_type
Definition TClass.cxx:373
IdMap_t::mapped_type mapped_type
Definition TClass.cxx:378
IdMap_t::const_iterator const_iterator
Definition TClass.cxx:372
IdMap_t::key_type key_type
Definition TClass.cxx:371
const std::string & GetNormalizedName() const
NormalizeThenLock(const NormalizeThenLock &)=delete
NormalizeThenLock(const char *cname)
NormalizeThenLock(NormalizeThenLock &&)=delete
NormalizeThenLock & operator=(const NormalizeThenLock &)=delete
NormalizeThenLock & operator=(NormalizeThenLock &&)=delete
This class registers for all classes their name, id and dictionary function in a hash table.
Definition TClassTable.h:38
static void PrintTable()
Print the class table.
static Int_t GetPragmaBits(const char *name)
Returns the pragma bits as specified in the LinkDef.h file.
static DictFuncPtr_t GetDict(const char *cname)
Given the class name returns the Dictionary() function of a class (uses hash of name).
static Version_t GetID(const char *cname)
Returns the ID of a class.
ROOT::TMapTypeToClassRec IdMap_t
Definition TClassTable.h:44
static void SortTable()
Sort the class table by ascending class ID's.
static TProtoClass * GetProtoNorm(const char *cname)
Given the class normalized name returns the TClassProto object for the class.
static DictFuncPtr_t GetDictNorm(const char *cname)
Given the normalized class name returns the Dictionary() function of a class (uses hash of name).
static ROOT::TClassAlt ** fgAlternate
Definition TClassTable.h:47
void Print(Option_t *option="") const override
Print the class table.
static void Terminate()
Deletes the class table (this static class function calls the dtor).
static TProtoClass * GetProto(const char *cname)
Given the class name returns the TClassProto object for the class.
static std::atomic< UInt_t > fgTally
Definition TClassTable.h:52
TClassTable()
TClassTable is a singleton (i.e. only one can exist per application).
static char * Next()
Returns next class from sorted class table.
static char * At(UInt_t index)
Returns class at index from sorted class table.
static Bool_t Check(const char *cname, std::string &normname)
static void Init()
static void Remove(const char *cname)
Remove a class from the class table.
static ROOT::TClassRec ** fgSortedTable
Definition TClassTable.h:49
static ROOT::TClassRec ** fgTable
Definition TClassTable.h:48
static IdMap_t * fgIdMap
Definition TClassTable.h:50
static Bool_t CheckClassTableInit()
Return true fs the table exist.
static void Add(const char *cname, Version_t id, const std::type_info &info, DictFuncPtr_t dict, Int_t pragmabits)
Add a class to the class table (this is a static function).
~TClassTable()
TClassTable singleton is deleted in Terminate().
static void RemoveAlternate(ROOT::TClassAlt *alt)
static ROOT::TClassRec * FindElement(const char *cname, Bool_t insert)
Find a class by name in the class table (using hash of name).
static std::vector< std::string > GetClassAlternativeNames(const char *cname)
static Bool_t fgSorted
Definition TClassTable.h:53
static UInt_t fgSize
Definition TClassTable.h:51
static ROOT::TClassAlt * AddAlternate(const char *normname, const char *alternate)
static UInt_t fgCursor
Definition TClassTable.h:54
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:84
Version_t fClassVersion
Definition TClass.h:225
void SetClassVersion(Version_t version)
Private function.
Definition TClass.cxx:5714
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition TClass.h:270
@ kHasTClassInit
Definition TClass.h:130
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:2973
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void RegisterTClassUpdate(TClass *oldcl, DictFuncPtr_t dict)=0
A doubly linked list.
Definition TList.h:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:575
void Add(TObject *obj) override
Definition TList.h:81
TMap implements an associative array of (key,value) pairs using a THashTable for efficient retrieval ...
Definition TMap.h:40
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Collectable string class.
Definition TObjString.h:28
TString & String()
Definition TObjString.h:48
Mother of all ROOT objects.
Definition TObject.h:41
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:1057
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition TObject.cxx:1099
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:1045
Class used by TMap to store (key,value) pairs.
Definition TMap.h:102
Persistent version of a TClass.
Definition TProtoClass.h:38
static Bool_t Initialized()
Return kTRUE if the TROOT object has been initialized.
Definition TROOT.cxx:2913
Regular expression class.
Definition TRegexp.h:31
Basic string class.
Definition TString.h:138
const char * Data() const
Definition TString.h:384
TString & Remove(Ssiz_t pos)
Definition TString.h:693
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:659
TLine * line
const Int_t n
Definition legend1.C:16
R__EXTERN TROOT * gROOTLocal
Definition TROOT.h:384
std::vector< std::pair< const char *, const char * > > & GetDelayedAddClassAlternate()
ROOT::TClassAlt * AddClassAlternate(const char *normName, const char *alternate)
Global function called by GenerateInitInstance.
std::vector< std::unique_ptr< TClassRec > > & GetDelayedAddClass()
void RemoveClass(const char *cname, TClass *cl)
Global function called by the dtor of a class's init class (see the ClassDef macro).
void AddClass(const char *cname, Version_t id, const std::type_info &info, DictFuncPtr_t dict, Int_t pragmabits)
Global function called by the ctor of a class's init class (see the ClassDef macro).
TNamed * RegisterClassTemplate(const char *name, const char *file, Int_t line)
Global function to register the implementation file and line of a class template (i....
static UInt_t ClassTableHash(const char *name, UInt_t size)
void ResetClassVersion(TClass *, const char *, Short_t)
Global function to update the version number.
TROOT * GetROOT()
Definition TROOT.cxx:477
void RemoveClassAlternate(ROOT::TClassAlt *)
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
void GetNormalizedName(std::string &norm_name, std::string_view name)
Return the normalized name.