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