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 ClassImp 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
60
61static std::mutex &GetClassTableMutex()
62{
63 static std::mutex sMutex;
64 return sMutex;
65}
66
67// RAII to first normalize the input classname (operation that
68// both requires the ROOT global lock and might call `TClassTable`
69// resursively) and then acquire a lock on `TClassTable` local
70// mutex.
72 std::string fNormalizedName;
73
74public:
80
82 {
84 return;
85
86 // The recorded name is normalized, let's make sure we convert the
87 // input accordingly. This operation will take the ROOT global lock
88 // and might call recursively `TClassTable`, so this must be done
89 // outside of the `TClassTable` critical section.
91
92 GetClassTableMutex().lock();
93 }
94
96 GetClassTableMutex().unlock();
97 }
98
99 const std::string &GetNormalizedName() const {
100 return fNormalizedName;
101 }
102};
103
104////////////////////////////////////////////////////////////////////////////////
105
106namespace ROOT {
107 class TClassRec {
108 public:
110 fName(nullptr), fId(0), fDict(nullptr), fInfo(nullptr), fProto(nullptr), fNext(next)
111 {}
112
114 // TClassTable::fgIdMap->Remove(r->fInfo->name());
115 delete [] fName;
116 delete fProto;
117 delete fNext;
118 }
119
120 char *fName;
124 const std::type_info *fInfo;
127 };
128
129 class TClassAlt {
130 public:
131 TClassAlt(const char*alternate, const char *normName, TClassAlt *next) :
133 {}
134
136 // Nothing more to delete.
137 }
138
139 const char *fName; // Do not own
140 const char *fNormName; // Do not own
141 std::unique_ptr<TClassAlt> fNext;
142 };
143
144#define R__USE_STD_MAP
146#if defined R__USE_STD_MAP
147 // This wrapper class allow to avoid putting #include <map> in the
148 // TROOT.h header file.
149 public:
150 typedef std::map<std::string, TClassRec*> IdMap_t;
154#ifdef R__WIN32
155 // Window's std::map does NOT defined mapped_type
156 typedef TClassRec* mapped_type;
157#else
159#endif
160
161 private:
163
164 public:
165 void Add(const key_type &key, mapped_type &obj) {
166 fMap[key] = obj;
167 }
168
169 mapped_type Find(const key_type &key) const {
170 IdMap_t::const_iterator iter = fMap.find(key);
171 mapped_type cl = nullptr;
172 if (iter != fMap.end()) cl = iter->second;
173 return cl;
174 }
175
176 void Remove(const key_type &key) { fMap.erase(key); }
177
178 void Print() {
179 Info("TMapTypeToClassRec::Print", "printing the typeinfo map in TClassTable");
180 for (const_iterator iter = fMap.begin(); iter != fMap.end(); ++iter) {
181 printf("Key: %40s 0x%zx\n", iter->first.c_str(), (size_t)iter->second);
182 }
183 }
184#else
185 private:
186 TMap fMap;
187 public:
188#ifdef R__COMPLETE_MEM_TERMINATION
190 TIter next(&fMap);
191 TObjString *key;
192 while((key = (TObjString*)next())) {
193 delete key;
194 }
195 }
196#endif
197
198 void Add(const char *key, TClassRec *&obj)
199 {
200 // Add <key,value> pair to the map.
201
202 TObjString *realkey = new TObjString(key);
203 fMap.Add(realkey, (TObject*)obj);
204 }
205
206 TClassRec *Find(const char *key) const {
207 // Find the value corresponding the key.
208 const TPair *a = (const TPair *)fMap.FindObject(key);
209 if (a) return (TClassRec*) a->Value();
210 return 0;
211 }
212
213 void Remove(const char *key) {
214 // Remove the value corresponding the key.
215 TObjString realkey(key);
216 TObject *actual = fMap.Remove(&realkey);
217 delete actual;
218 }
219
220 void Print() {
221 // Print the content of the map.
222 Info("TMapTypeToClassRec::Print", "printing the typeinfo map in TClassTable");
223 TIter next(&fMap);
224 TObjString *key;
225 while((key = (TObjString*)next())) {
226 printf("Key: %s\n",key->String().Data());
227 TClassRec *data = (TClassRec*)fMap.GetValue(key);
228 if (data) {
229 printf(" class: %s %d\n",data->fName,data->fId);
230 } else {
231 printf(" no class: \n");
232 }
233 }
234 }
235#endif
236 };
237
238 static UInt_t ClassTableHash(const char *name, UInt_t size)
239 {
240 auto p = reinterpret_cast<const unsigned char*>( name );
241 UInt_t slot = 0;
242
243 while (*p) slot = slot<<1 ^ *p++;
244 slot %= size;
245
246 return slot;
247 }
248
249 std::vector<std::unique_ptr<TClassRec>> &GetDelayedAddClass()
250 {
251 static std::vector<std::unique_ptr<TClassRec>> delayedAddClass;
252 return delayedAddClass;
253 }
254
255 std::vector<std::pair<const char *, const char *>> &GetDelayedAddClassAlternate()
256 {
257 static std::vector<std::pair<const char *, const char *>> delayedAddClassAlternate;
259 }
260}
261
262std::unordered_map<ROOT::TClassRec *, std::vector<ROOT::TClassAlt *>> &GetClassRecToAltMap()
263{
264 static std::unordered_map<ROOT::TClassRec *, std::vector<ROOT::TClassAlt *>> classRecToAltMap;
265 return classRecToAltMap;
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// TClassTable is a singleton (i.e. only one can exist per application).
270
272{
273 if (gClassTable) return;
274
275 fgSize = 1009; //this is the result of (int)TMath::NextPrime(1000);
276 fgTable = new TClassRec* [fgSize];
278 fgIdMap = new IdMap_t;
279 memset(fgTable, 0, fgSize * sizeof(TClassRec*));
280 memset(fgAlternate, 0, fgSize * sizeof(TClassAlt *));
281 gClassTable = this;
282
283 for (auto &&r : GetDelayedAddClass()) {
284 AddClass(r->fName, r->fId, *r->fInfo, r->fDict, r->fBits);
285 };
286 GetDelayedAddClass().clear();
287
288 for (auto &&r : GetDelayedAddClassAlternate()) {
289 AddAlternate(r.first, r.second);
290 }
292}
293
294////////////////////////////////////////////////////////////////////////////////
295/// TClassTable singleton is deleted in Terminate().
296
298{
299 // Try to avoid spurious warning from memory leak checkers.
300 if (gClassTable != this) return;
301
302 for (UInt_t i = 0; i < fgSize; i++) {
303 delete fgTable[i]; // Will delete all the elements in the chain.
304 }
305 delete [] fgTable; fgTable = nullptr;
306 delete [] fgSortedTable; fgSortedTable = nullptr;
307 delete fgIdMap; fgIdMap = nullptr;
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// Return true fs the table exist.
312/// If the table does not exist but the delayed list does, then
313/// create the table and return true.
314
316{
317 // This will be set at the lastest during TROOT construction, so before
318 // any threading could happen.
319 if (!gClassTable || !fgTable) {
320 if (GetDelayedAddClass().size()) {
321 new TClassTable;
322 return kTRUE;
323 }
324 return kFALSE;
325 }
326 return kTRUE;
327}
328
329////////////////////////////////////////////////////////////////////////////////
330/// Print the class table. Before printing the table is sorted
331/// alphabetically. Only classes specified in option are listed.
332/// The default is to list all classes.
333/// Standard wildcarding notation supported.
334
335void TClassTable::Print(Option_t *option) const
336{
337 std::lock_guard<std::mutex> lock(GetClassTableMutex());
338
339 // This is the very rare case (i.e. called before any dictionary load)
340 // so we don't need to execute this outside of the critical section.
341 if (fgTally == 0 || !fgTable)
342 return;
343
344 SortTable();
345
346 int n = 0, ninit = 0, nl = 0;
347
348 if (!option) option = "";
349 int nch = strlen(option);
350 TRegexp re(option, kTRUE);
351
352 Printf("\nDefined classes");
353 Printf("class version bits initialized");
354 Printf("================================================================");
355 for (UInt_t i = 0; i < fgTally; i++) {
357 if (!r) break;
358 n++;
359 TString s = r->fName;
360 if (nch && strcmp(option,r->fName) && s.Index(re) == kNPOS) continue;
361 nl++;
362 if (TClass::GetClass(r->fName, kFALSE)) {
363 ninit++;
364 Printf("%-35s %6d %7d Yes", r->fName, r->fId, r->fBits);
365 } else
366 Printf("%-35s %6d %7d No", r->fName, r->fId, r->fBits);
367 }
368 Printf("----------------------------------------------------------------");
369 Printf("Listed Classes: %4d Total classes: %4d initialized: %4d",nl, n, ninit);
370 Printf("================================================================\n");
371}
372
373//---- static members --------------------------------------------------------
374
375////////////////////////////////////////////////////////////////////////////////
376/// Returns class at index from sorted class table. Don't use this iterator
377/// while modifying the class table. The class table can be modified
378/// when making calls like TClass::GetClass(), etc.
379/// Returns 0 if index points beyond last class name.
380
382{
383 if (index < fgTally) {
384 std::lock_guard<std::mutex> lock(GetClassTableMutex());
385
386 SortTable();
388 if (r)
389 return r->fName;
390 }
391 return nullptr;
392}
393
394//______________________________________________________________________________
396//______________________________________________________________________________
398
399namespace ROOT { class TForNamespace {}; } // Dummy class to give a typeid to namespace (see also TGenericClassInfo)
400
401////////////////////////////////////////////////////////////////////////////////
402/// Add a class to the class table (this is a static function).
403/// Note that the given cname *must* be already normalized.
404
405void TClassTable::Add(const char *cname, Version_t id, const std::type_info &info,
407{
408 if (!cname || *cname == 0)
409 ::Fatal("TClassTable::Add()", "Failed to deduce type for '%s'", info.name());
410
411 // This will be set at the lastest during TROOT construction, so before
412 // any threading could happen.
413 if (!gClassTable)
414 new TClassTable;
415
416 std::unique_lock<std::mutex> lock(GetClassTableMutex());
417
418 // check if already in table, if so return
420 if (r->fName && r->fInfo) {
421 if ( strcmp(r->fInfo->name(), typeid(ROOT::TForNamespace).name()) ==0
422 && strcmp(info.name(), typeid(ROOT::TForNamespace).name()) ==0 ) {
423 // We have a namespace being reloaded.
424 // This okay we just keep the old one.
425 return;
426 }
428 lock.unlock(); // Warning might recursively call TClassTable during gROOT init
429 // Warn only for class that are not STD classes
430 ::Warning("TClassTable::Add", "class %s already in TClassTable", cname);
431 }
432 return;
433 } else if (ROOT::Internal::gROOTLocal && gCling) {
434 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
435 if (oldcl) { // && oldcl->GetClassInfo()) {
436 // As a work-around to ROOT-6012, we need to register the class even if
437 // it is not a template instance, because a forward declaration in the header
438 // files loaded by the current dictionary wil also de-activate the update
439 // class info mechanism!
440
441 // The TClass exist and already has a class info, so it must
442 // correspond to a class template instantiation which the interpreter
443 // was able to make with the library containing the TClass Init.
444 // Because it is already known to the interpreter, the update class info
445 // will not be triggered, we need to force it.
447 }
448 }
449
450 if (!r->fName)
451 r->fName = StrDup(cname);
452 r->fId = id;
453 r->fBits = pragmabits;
454 r->fDict = dict;
455 r->fInfo = &info;
456
457 fgIdMap->Add(info.name(),r);
458
460}
461
462////////////////////////////////////////////////////////////////////////////////
463/// Add a class to the class table (this is a static function).
464/// The caller of this function should be holding the ROOT Write lock.
465
467{
468 // This will be set at the lastest during TROOT construction, so before
469 // any threading could happen.
470 if (!gClassTable)
471 new TClassTable;
472
473 std::unique_lock<std::mutex> lock(GetClassTableMutex());
474
475 // By definition the name in the TProtoClass is (must be) the normalized
476 // name, so there is no need to tweak it.
477 const char *cname = proto->GetName();
478
479 // check if already in table, if so return
481 if (r->fName) {
482 if (r->fProto) delete r->fProto;
483 r->fProto = proto;
484 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
485
486 lock.unlock(); // FillTClass might recursively call TClassTable during gROOT init
487 if (oldcl && oldcl->GetState() == TClass::kHasTClassInit)
488 proto->FillTClass(oldcl);
489 return;
490 } else if (ROOT::Internal::gROOTLocal && gCling) {
491 TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(cname);
492 if (oldcl) { // && oldcl->GetClassInfo()) {
493 // As a work-around to ROOT-6012, we need to register the class even if
494 // it is not a template instance, because a forward declaration in the header
495 // files loaded by the current dictionary wil also de-activate the update
496 // class info mechanism!
497
498 lock.unlock(); // Warning might recursively call TClassTable during gROOT init
499 ::Warning("TClassTable::Add(TProtoClass*)","Called for existing class without a prior call add the dictionary function.");
500 }
501 }
502
503 r->fName = StrDup(cname);
504 r->fId = 0;
505 r->fBits = 0;
506 r->fDict = nullptr;
507 r->fInfo = nullptr;
508 r->fProto= proto;
509
511}
512
513////////////////////////////////////////////////////////////////////////////////
514
516{
517 // This will be set at the lastest during TROOT construction, so before
518 // any threading could happen.
519 if (!gClassTable)
520 new TClassTable;
521
522 std::lock_guard<std::mutex> lock(GetClassTableMutex());
523
525
526 for (const TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
527 if (strcmp(alternate,a->fName)==0) {
528 if (strcmp(normName,a->fNormName) != 0) {
529 fprintf(stderr,"Error in TClassTable::AddAlternate: "
530 "Second registration of %s with a different normalized name (old: '%s', new: '%s')\n",
531 alternate, a->fNormName, normName);
532 }
533 return nullptr;
534 }
535 }
536
538
540 if (fgTable[slotNorm]) {
542 // Let others connect a class record to its class alternative names
543 if (auto it = classToAlt.find(fgTable[slotNorm]); it == classToAlt.end())
544 classToAlt[fgTable[slotNorm]] = std::vector<ROOT::TClassAlt *>{fgAlternate[slot]};
545 else
547 }
548
549 return fgAlternate[slot];
550}
551
552////////////////////////////////////////////////////////////////////////////////
553///
555{
556 if (!alt || !gClassTable)
557 return;
558
559 std::lock_guard<std::mutex> lock(GetClassTableMutex());
560
562
563 if (!fgAlternate[slot])
564 return;
565
566 if (fgAlternate[slot] == alt)
567 fgAlternate[slot] = alt->fNext.release();
568 else {
569 for (TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
570 if (a->fNext.get() == alt) {
571 a->fNext.swap( alt->fNext );
572 assert( alt == alt->fNext.get());
573 alt->fNext.release();
574 }
575 }
576 }
577 delete alt;
578}
579
580////////////////////////////////////////////////////////////////////////////////
581
582Bool_t TClassTable::Check(const char *cname, std::string &normname)
583{
584 if (!CheckClassTableInit())
585 return kFALSE;
586
587 std::lock_guard<std::mutex> lock(GetClassTableMutex());
588
590
591 // Check if 'cname' is a known normalized name.
592 for (TClassRec *r = fgTable[slot]; r; r = r->fNext)
593 if (strcmp(cname,r->fName)==0) return kTRUE;
594
595 // See if 'cname' is register in the list of alternate names
596 for (const TClassAlt *a = fgAlternate[slot]; a; a = a->fNext.get()) {
597 if (strcmp(cname,a->fName)==0) {
598 normname = a->fNormName;
599 return kTRUE;
600 }
601 }
602
603 return kFALSE;
604}
605
606////////////////////////////////////////////////////////////////////////////////
607/// Remove a class from the class table. This happens when a shared library
608/// is unloaded (i.e. the dtor's of the global init objects are called).
609
610void TClassTable::Remove(const char *cname)
611{
612 if (!CheckClassTableInit())
613 return;
614
615 std::lock_guard<std::mutex> lock(GetClassTableMutex());
616
618
619 TClassRec *r;
620 TClassRec *prev = nullptr;
621 for (r = fgTable[slot]; r; r = r->fNext) {
622 if (!strcmp(r->fName, cname)) {
623 if (prev)
624 prev->fNext = r->fNext;
625 else
626 fgTable[slot] = r->fNext;
627 fgIdMap->Remove(r->fInfo->name());
628 r->fNext = nullptr; // Do not delete the others.
629 delete r;
630 fgTally--;
632 break;
633 }
634 prev = r;
635 }
636}
637
638////////////////////////////////////////////////////////////////////////////////
639/// Find a class by name in the class table (using hash of name). Returns
640/// 0 if the class is not in the table. Unless arguments insert is true in
641/// which case a new entry is created and returned.
642/// `cname` must be the normalized name of the class.
643
645{
646 // Internal routine, no explicit lock needed here.
647
649
650 for (TClassRec *r = fgTable[slot]; r; r = r->fNext)
651 if (strcmp(cname, r->fName) == 0)
652 return r;
653
654 if (!insert)
655 return nullptr;
656
658
659 fgTally++;
660 return fgTable[slot];
661}
662
663////////////////////////////////////////////////////////////////////////////////
664/// Returns the ID of a class.
665
667{
669
670 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
671 if (r)
672 return r->fId;
673 return -1;
674}
675
676////////////////////////////////////////////////////////////////////////////////
677/// Returns the pragma bits as specified in the LinkDef.h file.
678
680{
682
683 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
684 if (r)
685 return r->fBits;
686 return 0;
687}
688
689////////////////////////////////////////////////////////////////////////////////
690/// Given the class name returns the Dictionary() function of a class
691/// (uses hash of name).
692
694{
695 if (gDebug > 9) {
696 ::Info("GetDict", "searches for %s", cname);
697 fgIdMap->Print();
698 }
700
701 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
702 if (r)
703 return r->fDict;
704 return nullptr;
705}
706
707////////////////////////////////////////////////////////////////////////////////
708/// Given the std::type_info returns the Dictionary() function of a class
709/// (uses hash of std::type_info::name()).
710
712{
713 if (!CheckClassTableInit())
714 return nullptr;
715
716 if (gDebug > 9)
717 ROOT::GetROOT(); // Info might recursively call TClassTable during the gROOT init
718
719 std::lock_guard<std::mutex> lock(GetClassTableMutex());
720
721 if (gDebug > 9) {
722 ::Info("GetDict", "searches for %s at 0x%zx", info.name(), (size_t)&info);
723 fgIdMap->Print();
724 }
725
726 TClassRec *r = fgIdMap->Find(info.name());
727 if (r)
728 return r->fDict;
729 return nullptr;
730}
731
732////////////////////////////////////////////////////////////////////////////////
733/// Given the normalized class name returns the Dictionary() function of a class
734/// (uses hash of name).
735
737{
738 if (!CheckClassTableInit())
739 return nullptr;
740
741 if (gDebug > 9)
742 ROOT::GetROOT(); // Info might recursively call TClassTable during the gROOT init
743
744 std::lock_guard<std::mutex> lock(GetClassTableMutex());
745
746 if (gDebug > 9) {
747 ::Info("GetDict", "searches for %s", cname);
748 fgIdMap->Print();
749 }
750
752 if (r)
753 return r->fDict;
754 return nullptr;
755}
756
757////////////////////////////////////////////////////////////////////////////////
758/// Given the class name returns the TClassProto object for the class.
759/// (uses hash of name).
760
762{
763 if (gDebug > 9) {
764 ::Info("GetDict", "searches for %s", cname);
765 }
766
767 if (!CheckClassTableInit())
768 return nullptr;
769
771
772 if (gDebug > 9) {
773 // Because of the early call to Info, gROOT is already initialized
774 // and thus this will not cause a recursive call to TClassTable.
775 ::Info("GetDict", "searches for %s", cname);
776 fgIdMap->Print();
777 }
778
779 TClassRec *r = FindElement(guard.GetNormalizedName().c_str(), kFALSE);
780 if (r)
781 return r->fProto;
782 return nullptr;
783}
784
785////////////////////////////////////////////////////////////////////////////////
786/// Given the class normalized name returns the TClassProto object for the class.
787/// (uses hash of name).
788
790{
791 if (gDebug > 9) {
792 ::Info("GetDict", "searches for %s", cname);
793 }
794
795 if (!CheckClassTableInit())
796 return nullptr;
797
798 std::lock_guard<std::mutex> lock(GetClassTableMutex());
799
800 if (gDebug > 9) {
801 fgIdMap->Print();
802 }
803
805 if (r)
806 return r->fProto;
807 return nullptr;
808}
809
810////////////////////////////////////////////////////////////////////////////////
811
812extern "C" {
813 static int ClassComp(const void *a, const void *b)
814 {
815 // Function used for sorting classes alphabetically.
816
817 return strcmp((*(TClassRec **)a)->fName, (*(TClassRec **)b)->fName);
818 }
819}
820
821////////////////////////////////////////////////////////////////////////////////
822/// Returns next class from sorted class table. Don't use this iterator
823/// while modifying the class table. The class table can be modified
824/// when making calls like TClass::GetClass(), etc.
825
827{
828 std::lock_guard<std::mutex> lock(GetClassTableMutex());
829
830 if (fgCursor < fgTally) {
832 return r->fName;
833 }
834
835 return nullptr;
836}
837
838////////////////////////////////////////////////////////////////////////////////
839/// Print the class table. Before printing the table is sorted
840/// alphabetically.
841
843{
844 if (fgTally == 0 || !fgTable)
845 return;
846
847 std::lock_guard<std::mutex> lock(GetClassTableMutex());
848
849 SortTable();
850
851 int n = 0, ninit = 0;
852
853 Printf("\nDefined classes");
854 Printf("class version bits initialized");
855 Printf("================================================================");
856 UInt_t last = fgTally;
857 for (UInt_t i = 0; i < last; i++) {
859 if (!r) break;
860 n++;
861 // Do not use TClass::GetClass to avoid any risk of autoloading.
862 if (gROOT->GetListOfClasses()->FindObject(r->fName)) {
863 ninit++;
864 Printf("%-35s %6d %7d Yes", r->fName, r->fId, r->fBits);
865 } else
866 Printf("%-35s %6d %7d No", r->fName, r->fId, r->fBits);
867 }
868 Printf("----------------------------------------------------------------");
869 Printf("Total classes: %4d initialized: %4d", n, ninit);
870 Printf("================================================================\n");
871}
872
873////////////////////////////////////////////////////////////////////////////////
874/// Sort the class table by ascending class ID's.
875
877{
878 // Internal routine.
879
880 if (!fgSorted) {
881 delete [] fgSortedTable;
883
884 int j = 0;
885 for (UInt_t i = 0; i < fgSize; i++)
886 for (TClassRec *r = fgTable[i]; r; r = r->fNext)
887 fgSortedTable[j++] = r;
888
890 fgSorted = kTRUE;
891 }
892}
893
894////////////////////////////////////////////////////////////////////////////////
895/// Deletes the class table (this static class function calls the dtor).
896
898{
899 if (gClassTable) {
900 for (UInt_t i = 0; i < fgSize; i++)
901 delete fgTable[i]; // Will delete all the elements in the chain.
902
903 delete [] fgTable; fgTable = nullptr;
904 delete [] fgSortedTable; fgSortedTable = nullptr;
905 delete fgIdMap; fgIdMap = nullptr;
906 fgSize = 0;
908 }
909}
910
911////////////////////////////////////////////////////////////////////////////////
912/// Global function called by the ctor of a class's init class
913/// (see the ClassImp macro).
914
915void ROOT::AddClass(const char *cname, Version_t id,
916 const std::type_info& info,
917 DictFuncPtr_t dict,
919{
920 if (!TROOT::Initialized() && !gClassTable) {
921 auto r = std::unique_ptr<TClassRec>(new TClassRec(nullptr));
922 r->fName = StrDup(cname);
923 r->fId = id;
924 r->fBits = pragmabits;
925 r->fDict = dict;
926 r->fInfo = &info;
927 GetDelayedAddClass().emplace_back(std::move(r));
928 } else {
930 }
931}
932
933////////////////////////////////////////////////////////////////////////////////
934/// Global function called by GenerateInitInstance.
935/// (see the ClassImp macro).
936
938{
939 if (!TROOT::Initialized() && !gClassTable) {
941 // If a library is loaded before gROOT is initialized we can assume
942 // it is hard linked along side libCore (or is libCore) thus can't
943 // really be unloaded.
944 return nullptr;
945 } else {
947 }
948}
949
951{
952 // This routine is meant to be called (indirectly) by dlclose so we
953 // we are guaranteed that the library initialization has completed.
955}
956
957////////////////////////////////////////////////////////////////////////////////
958/// Global function to update the version number.
959/// This is called via the RootClassVersion macro.
960///
961/// if cl!=0 and cname==-1, set the new class version if and only is
962/// greater than the existing one and greater or equal to 2;
963/// and also ignore the request if fVersionUsed is true.
964///
965/// Note on class version number:
966/// - If no class has been specified, TClass::GetVersion will return -1
967/// - The Class Version 0 request the whole object to be transient
968/// - The Class Version 1, unless specify via ClassDef indicates that the
969/// I/O should use the TClass checksum to distinguish the layout of the class
971{
972 if (cname && cname != (void*)-1 && TClassTable::CheckClassTableInit()) {
975 if (r)
976 r->fId = newid;
977 }
978 if (cl) {
979 if (cl->fVersionUsed) {
980 // Problem, the reset is called after the first usage!
981 if (cname!=(void*)-1)
982 Error("ResetClassVersion","Version number of %s can not be changed after first usage!",
983 cl->GetName());
984 } else {
985 if (newid < 0) {
986 Error("SetClassVersion","The class version (for %s) must be positive (value %d is ignored)",cl->GetName(),newid);
987 }
988 if (cname==(void*)-1) {
989 if (cl->fClassVersion<newid && 2<=newid) {
991 }
992 } else {
994 }
995 }
996 }
997}
998
999////////////////////////////////////////////////////////////////////////////////
1000/// Global function called by the dtor of a class's init class
1001/// (see the ClassImp macro).
1002/// The caller of this function should be holding the ROOT Write lock.
1003
1005{
1006 // don't delete class information since it is needed by the I/O system
1007 // to write the StreamerInfo to file
1008 if (cname) {
1009 // Let's still remove this information to allow reloading later.
1010 // Anyway since the shared library has been unloaded, the dictionary
1011 // pointer is now invalid ....
1012 // We still keep the TClass object around because TFile needs to
1013 // get to the TStreamerInfo.
1014 if (oldcl)
1015 oldcl->SetUnloaded();
1017 }
1018}
1019
1020////////////////////////////////////////////////////////////////////////////////
1021/// Global function to register the implementation file and line of
1022/// a class template (i.e. NOT a concrete class).
1023
1024TNamed *ROOT::RegisterClassTemplate(const char *name, const char *file,
1025 Int_t line)
1026{
1027 static TList table;
1028 static Bool_t isInit = []() {
1029 table.SetOwner(kTRUE);
1030 table.UseRWLock();
1031 return true;
1032 }();
1033 (void)isInit;
1034
1035 TString classname(name);
1036 Ssiz_t loc = classname.Index("<");
1037 if (loc >= 1)
1038 classname.Remove(loc);
1039 TNamed *reg = (TNamed*)table.FindObject(classname);
1040 if (file) {
1041 if (reg)
1042 reg->SetTitle(file);
1043 else {
1044 reg = new TNamed((const char*)classname, file);
1045 table.Add(reg);
1046 }
1047 reg->SetUniqueID(line);
1048 }
1049 return reg;
1050}
1051
1052std::vector<std::string> TClassTable::GetClassAlternativeNames(const char *cname)
1053{
1054 std::lock_guard<std::mutex> lock(GetClassTableMutex());
1055
1057 if (!fgTable[slot])
1058 return {};
1059 const auto &classRecToAltMap = GetClassRecToAltMap();
1060 if (auto it = classRecToAltMap.find(fgTable[slot]); it == classRecToAltMap.end())
1061 return {};
1062
1063 const auto &classAlts = classRecToAltMap.at(fgTable[slot]);
1064 std::vector<std::string> ret;
1065 ret.reserve(classAlts.size());
1066 for (const auto *classAlt : classAlts) {
1067 ret.push_back(classAlt->fName);
1068 }
1069
1070 return ret;
1071}
#define SafeDelete(p)
Definition RConfig.hxx:525
#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
Definition RtypesCore.h:63
short Version_t
Definition RtypesCore.h:65
unsigned int UInt_t
Definition RtypesCore.h:46
short Short_t
Definition RtypesCore.h:39
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:117
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
TClass *(* DictFuncPtr_t)()
Definition Rtypes.h:86
#define ClassImp(name)
Definition Rtypes.h:376
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 Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
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
Definition TROOT.cxx:622
#define gROOT
Definition TROOT.h:414
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2503
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2557
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:224
void SetClassVersion(Version_t version)
Private function.
Definition TClass.cxx:5820
std::atomic< Bool_t > fVersionUsed
saved remember if fOffsetStreamer has been set.
Definition TClass.h:266
@ 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:3079
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:576
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
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:2911
Regular expression class.
Definition TRegexp.h:31
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:376
TString & Remove(Ssiz_t pos)
Definition TString.h:685
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
TLine * line
std::ostream & Info()
Definition hadd.cxx:177
const Int_t n
Definition legend1.C:16
R__EXTERN TROOT * gROOTLocal
Definition TROOT.h:387
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
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 ClassImp 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 ClassImp 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:472
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.