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