ATLAS Offline Software
Loading...
Searching...
No Matches
BaseInfo.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
13
17#include "GaudiKernel/System.h"
18#include <mutex>
19#include <map>
20#include <unordered_map>
21#include <algorithm>
22#include <iostream>
23#include "string.h"
24
25
26namespace SG {
27
28
31 struct info {
33 info (BaseInfoBase::castfn_t* converter = 0,
34 BaseInfoBase::castfn_t* converterTo = 0,
35 bool is_virtual = false);
36
40
45
49 };
50
51
54
57 bool m_needs_init{true};
58
60 const std::type_info* m_typeinfo{};
61
62
64 typedef std::pair<const std::type_info*, info> ti_map_pair_type;
65 typedef std::vector<ti_map_pair_type> ti_map_type;
67
68
70 typedef std::pair<const std::type_info*, const CopyConversionBase*>
72 typedef std::vector<ti_copyconversion_pair_type> ti_copyconversion_type;
74
75
77 typedef std::unordered_map<const std::type_info*, BaseInfoBase*> bi_by_ti_map_type;
79
80
82 typedef std::unordered_map<std::string, const std::type_info*> ti_by_name_map_type;
84
85
88 typedef std::unordered_multimap<const std::type_info*,
90 static init_list_t* s_init_list ATLAS_THREAD_SAFE;
91
92
93 // To make sure that the maps get deleted at program termination.
94 struct Deleter {
95 ~Deleter();
96 };
98
100
102 typedef std::mutex mutex_t;
103 typedef std::lock_guard<mutex_t> lock_t;
104 static mutex_t s_mutex ATLAS_THREAD_SAFE; // For the static variables.
105 mutable mutex_t m_mutex; // For the class members.
106
107
111
112
120 const info* findInfo (const std::type_info& tinfo) const
121 {
122 // We don't expect there to be many entries, so just use a linear search.
123 for (const auto& i : m_timap) {
124 if (i.first == &tinfo)
125 return &i.second;
126 }
127
128 // Sometimes type_info's are not actually unique, depending on how libraries
129 // get loaded. Try again, comparing names.
130 for (const auto& i : m_timap) {
131 if (strcmp (i.first->name(), tinfo.name()) == 0)
132 return &i.second;
133 }
134 return nullptr;
135 }
136};
137
138
139
144{
146 return m_impl->m_clid;
147}
148
149
153const std::type_info& BaseInfoBase::typeinfo() const
154{
156 return *m_impl->m_typeinfo;
157}
158
159
168void* BaseInfoBase::cast (void* p, CLID clid) const
169{
170 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
171 if (ti)
172 return this->cast (p, *ti);
173 return 0;
174}
175
176
185void* BaseInfoBase::cast (void* p, const std::type_info& tinfo) const
186{
187 if (BaseInfoBase::castfn_t* converter = castfn (tinfo)) {
188 return converter (p);
189 }
190 return nullptr;
191}
192
193
203void* BaseInfoBase::castTo (void* p, CLID clid) const
204{
205 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
206 if (ti)
207 return this->castTo (p, *ti);
208 return 0;
209}
210
211
221void* BaseInfoBase::castTo (void* p, const std::type_info& tinfo) const
222{
223 if (BaseInfoBase::castfn_t* converterTo = castfnTo (tinfo)) {
224 return converterTo (p);
225 }
226 return nullptr;
227}
228
229
239{
240 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
241 if (ti)
242 return this->castfn (*ti);
243 return 0;
244}
245
246
256BaseInfoBase::castfn (const std::type_info& tinfo) const
257{
259 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
260 if (i)
261 return i->m_converter;
262 return nullptr;
263}
264
265
275{
276 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
277 if (ti)
278 return this->castfnTo (*ti);
279 return 0;
280}
281
282
292BaseInfoBase::castfnTo (const std::type_info& tinfo) const
293{
295 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
296 if (i)
297 return i->m_converterTo;
298 return nullptr;
299}
300
301
306const std::vector<CLID>& BaseInfoBase::get_bases() const
307{
308 if (!m_impl->m_bases.isValid()) {
310 const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
311 std::vector<CLID> v;
312 v.reserve (map.size());
313 for (const auto& p : map) {
315 if (clid != CLID_NULL)
316 v.push_back (clid);
317 }
318 m_impl->m_bases.set (std::move (v));
319 }
320 return *m_impl->m_bases.ptr();
321}
322
323
328std::vector<const std::type_info*> BaseInfoBase::get_ti_bases() const
329{
331 const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
332 std::vector<const std::type_info*> v;
333 v.reserve (map.size());
334 for (const auto& i : map)
335 v.push_back (i.first);
336 return v;
337}
338
339
347{
348 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
349 if (ti)
350 return this->is_base (*ti);
351 return 0;
352}
353
354
361bool BaseInfoBase::is_base (const std::type_info& tinfo) const
362{
364 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
365 return i != 0;
366}
367
368
376{
377 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
378 if (ti)
379 return this->is_virtual (*ti);
380 return false;
381}
382
383
390bool BaseInfoBase::is_virtual (const std::type_info& tinfo) const
391{
393 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
394 if (i)
395 return i->m_is_virtual;
396 return false;
397}
398
399
407BaseInfoBase::copy_conversion (const std::type_info& tinfo) const
408{
410 for (const auto& p : m_impl->m_ti_copyconversion_map) {
411 if (p.first == &tinfo)
412 return p.second;
413 }
414 return 0;
415}
416
417
426{
427 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
428 if (ti)
429 return this->copy_conversion (*ti);
430 return 0;
431}
432
433
438void BaseInfoBase::destroy (void* p) const
439{
441 if (m_impl->m_destroy)
442 m_impl->m_destroy (p);
443}
444
445
453void
454BaseInfoBase::add_copy_conversion (const std::type_info& tinfo,
455 const CopyConversionBase* cnv)
456{
458 m_impl->m_ti_copyconversion_map.emplace_back (&tinfo, cnv);
459}
460
461
468std::vector<CLID>
470{
472 std::vector<CLID> out;
473 out.reserve (m_impl->m_ti_copyconversion_map.size());
474 for (const auto& i : m_impl->m_ti_copyconversion_map) {
476 if (clid != CLID_NULL)
477 out.push_back (clid);
478 }
479 return out;
480}
481
482
493void BaseInfoBase::add_info (const std::type_info& tinfo,
494 castfn_t* converter,
495 castfn_t* converterTo,
496 bool is_virtual)
497{
498 BaseInfoBaseImpl::lock_t slock (BaseInfoBaseImpl::s_mutex);
500 {
501 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
502 if (!i) {
503 m_impl->m_timap.emplace_back (&tinfo,
504 BaseInfoBaseImpl::info (converter, converterTo, is_virtual));
505 }
506 }
507
508 auto i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
509 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
510 BaseInfoBaseImpl& impl = *i->second->m_impl;
511 if (impl.m_clid == CLID_NULL)
512 impl.m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
513 }
514}
515
516
530 BaseInfoBase::castfn_t* converterTo /*= 0*/,
531 bool is_virtual /*= false*/)
532 : m_converter (converter),
533 m_converterTo (converterTo),
534 m_is_virtual (is_virtual)
535{
536}
537
538
543BaseInfoBase::BaseInfoBase (const std::type_info& tinfo,
546{
547 m_impl->m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
548 m_impl->m_typeinfo = &tinfo;
549 m_impl->m_destroy = destroy;
550 m_impl->m_needs_init = true;
551
552 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
553 if (!BaseInfoBaseImpl::s_bi_by_ti)
554 BaseInfoBaseImpl::s_bi_by_ti = new BaseInfoBaseImpl::bi_by_ti_map_type;
555 if (!BaseInfoBaseImpl::s_ti_by_name)
556 BaseInfoBaseImpl::s_ti_by_name = new BaseInfoBaseImpl::ti_by_name_map_type;
557
558 // Register this instance in the static maps.
559 (*BaseInfoBaseImpl::s_bi_by_ti)[&tinfo] = this;
560 (*BaseInfoBaseImpl::s_ti_by_name)[tinfo.name()] = &tinfo;
561}
562
563
568{
569 for (BaseInfoBaseImpl::ti_copyconversion_type::iterator it =
570 m_impl->m_ti_copyconversion_map.begin();
571 it != m_impl->m_ti_copyconversion_map.end();
572 ++it)
573 {
574 delete it->second;
575 }
576 delete m_impl;
577}
578
579
587{
588 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
589 if (ti)
590 return BaseInfoBase::find (*ti);
591 return 0;
592}
593
594
602BaseInfoBase* BaseInfoBase::find1 (const std::type_info& tinfo)
603{
604 BaseInfoBase* bib = nullptr;
605 {
606 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
607 if (!BaseInfoBaseImpl::s_bi_by_ti) return 0;
608 BaseInfoBaseImpl::bi_by_ti_map_type::iterator i =
609 BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
610 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
611 bib = i->second;
613 if (!bib->m_impl->m_needs_init)
614 return bib;
615 bib->m_impl->m_needs_init = false;
616 }
617 }
618
619 // Try the initlist.
620 while (true) {
621 BaseInfoBase::init_func_t* init = nullptr;
622 {
623 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
624 if (!BaseInfoBaseImpl::s_init_list) break;
625 BaseInfoBaseImpl::bi_by_ti_map_type::iterator i =
626 BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
627 if (i != BaseInfoBaseImpl::s_bi_by_ti->end())
628 bib = i->second;
629 BaseInfoBaseImpl::init_list_t::iterator it =
630 BaseInfoBaseImpl::s_init_list->find (&tinfo);
631 if (it == BaseInfoBaseImpl::s_init_list->end()) break;
632 init = it->second;
633 BaseInfoBaseImpl::s_init_list->erase (it);
634 }
635 init (bib);
636 }
637
638 return bib;
639}
640
641
649const BaseInfoBase* BaseInfoBase::find (const std::type_info& tinfo)
650{
651 BaseInfoBase* bib = find1 (tinfo);
652
653 // If we didn't find it, try looking up by name.
654 // This to deal with the issue of sometimes getting duplicate
655 // @c std::type_info instances.
656 if (!bib) {
657 const std::type_info* tinfo2 = nullptr;
658 {
659 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
660 if (BaseInfoBaseImpl::s_ti_by_name) {
661 BaseInfoBaseImpl::ti_by_name_map_type::iterator i =
662 BaseInfoBaseImpl::s_ti_by_name->find (tinfo.name());
663 if (i != BaseInfoBaseImpl::s_ti_by_name->end() && i->second != &tinfo) {
664 tinfo2 = i->second;
665 }
666 }
667 }
668 if (tinfo2) {
669 bib = find1 (*tinfo2);
670 }
671 }
672
673 if (bib) {
676 if (impl.m_clid == CLID_NULL)
677 impl.m_clid = CLIDRegistry::typeinfoToCLID (*impl.m_typeinfo);
678 }
679
680 return bib;
681}
682
683
689void BaseInfoBase::addInit (const std::type_info* tinfo,
690 init_func_t* init_func)
691{
692 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
693 if (!BaseInfoBaseImpl::s_init_list)
694 BaseInfoBaseImpl::s_init_list =
696 BaseInfoBaseImpl::s_init_list->insert (std::make_pair (tinfo, init_func));
697
698 if (BaseInfoBaseImpl::s_bi_by_ti) {
699 auto i = BaseInfoBaseImpl::s_bi_by_ti->find (tinfo);
700 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
701 BaseInfoBaseImpl::lock_t lock (i->second->m_impl->m_mutex);
702 BaseInfoBaseImpl& impl = *i->second->m_impl;
703 impl.m_needs_init = true;
704 if (impl.m_clid == CLID_NULL)
705 impl.m_clid = CLIDRegistry::typeinfoToCLID (*tinfo);
706 }
707 }
708}
709
710
715{
716 // This may be null during initialization, if we're initializing a
717 // BaseInfo<T>::s_instance instance which references another type
718 // for which the s_instance constructor has not yet been run.
719 if (!m_impl) return;
720
721 bool needs_init = false;
722 const std::type_info* ti = nullptr;
723 {
725 needs_init = m_impl->m_needs_init;
726 ti = m_impl->m_typeinfo;
727 }
728
729 if (needs_init)
730 find (*ti);
731}
732
733
734
736BaseInfoBaseImpl::bi_by_ti_map_type* BaseInfoBaseImpl::s_bi_by_ti = 0;
737BaseInfoBaseImpl::ti_by_name_map_type* BaseInfoBaseImpl::s_ti_by_name = 0;
738BaseInfoBaseImpl::init_list_t* BaseInfoBaseImpl::s_init_list = 0;
739BaseInfoBaseImpl::mutex_t BaseInfoBaseImpl::s_mutex;
740
741// To get them deleted.
744{
745 delete s_bi_by_ti;
746 delete s_ti_by_name;
747 delete s_init_list;
748}
749
750
751// Helper for dumping within the debugger.
753{
754 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
755 std::cout << "map:\n";
756 if (BaseInfoBaseImpl::s_bi_by_ti) {
757 std::vector<const std::type_info*> vv;
758 for (const auto& x : *BaseInfoBaseImpl::s_bi_by_ti)
759 vv.push_back (x.first);
760 std::sort (vv.begin(), vv.end());
761 for (const std::type_info* ti : vv)
762 {
763 const BaseInfoBase* bib = (*BaseInfoBaseImpl::s_bi_by_ti)[ti];
764 std::cout << ti << " " << bib->clid() << " [" << System::typeinfoName (*ti)
765 << "]\n";
766 }
767 }
768
769 std::cout << "\ninitlist:\n";
770 if (BaseInfoBaseImpl::s_init_list) {
771 for (const auto& x : *BaseInfoBaseImpl::s_init_list)
772 std::cout << x.first << " " << x.second << " ["
773 << System::typeinfoName (*x.first) << "]\n";
774 }
775}
776
777
778} // namespace SG
a static registry of CLID->typeName entries.
Cached value with atomic update.
Provide an interface for finding inheritance information at run time.
uint32_t CLID
The Class ID type.
#define x
static CLID typeinfoToCLID(const std::type_info &ti)
Return the CLID corresponding to a type_info.
static const std::type_info * CLIDToTypeinfo(CLID clid)
Translate between CLID and type_info.
Cached value with atomic update.
Definition CachedValue.h:55
The non-template portion of the BaseInfo implementation.
static BaseInfoBase * find1(const std::type_info &tinfo)
Helper for find.
Definition BaseInfo.cxx:602
BaseInfoBase(const std::type_info &tinfo, destroy_fn *destroy)
Constructor.
Definition BaseInfo.cxx:543
const CopyConversionBase * copy_conversion(const std::type_info &tinfo) const
Search for a copy conversion to tinfo.
Definition BaseInfo.cxx:407
void add_info(const std::type_info &tinfo, castfn_t *converter, castfn_t *converterTo, bool is_virtual)
Add information about one base class.
Definition BaseInfo.cxx:493
void add_copy_conversion(const std::type_info &tinfo, const CopyConversionBase *cnv)
Add a new copy conversion.
Definition BaseInfo.cxx:454
void maybeInit()
Run initializations for this class, if needed.
Definition BaseInfo.cxx:714
void init_func_t(BaseInfoBase *bib)
Type for an initialization function.
~BaseInfoBase()
Destructor.
Definition BaseInfo.cxx:567
std::vector< const std::type_info * > get_ti_bases() const
Return the type_info's of all known bases of T.
Definition BaseInfo.cxx:328
castfn_t * castfnTo(CLID clid) const
Return a function for casting to a derived pointer.
Definition BaseInfo.cxx:274
void * castTo(void *p, CLID clid) const
Cast to a derived pointer.
Definition BaseInfo.cxx:203
CLID clid() const
Return the CLID for this class.
Definition BaseInfo.cxx:143
static void addInit(const std::type_info *tinfo, init_func_t *init_func)
Register an initialization function.
Definition BaseInfo.cxx:689
void destroy(void *p) const
Delete an instance of the described type.
Definition BaseInfo.cxx:438
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition BaseInfo.cxx:586
const std::type_info & typeinfo() const
Return the std::type_info for this class.
Definition BaseInfo.cxx:153
void * cast(void *p, CLID clid) const
Cast to a base pointer.
Definition BaseInfo.cxx:168
castfn_t * castfn(CLID clid) const
Return a function for casting to a base pointer.
Definition BaseInfo.cxx:238
const std::vector< CLID > & get_bases() const
Return the class IDs of all known bases of T (that have class IDs).
Definition BaseInfo.cxx:306
bool is_base(CLID clid) const
Return true if clid is the ID of a class that is known to be a base of T.
Definition BaseInfo.cxx:346
bool is_virtual(CLID clid) const
Return true if clid is the ID of a class that is known to be a virtual base of T.
Definition BaseInfo.cxx:375
std::vector< CLID > get_copy_conversions() const
Return known copy conversions.
Definition BaseInfo.cxx:469
BaseInfoBaseImpl * m_impl
Pointer to internal state.
void * castfn_t(void *p)
Type of a pointer conversion function.
STL class.
Forward declaration.
void dumpBaseInfo()
Definition BaseInfo.cxx:752
virtual void lock() override
Lock the container.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
Structure to hold information about one base.
Definition BaseInfo.cxx:31
info(BaseInfoBase::castfn_t *converter=0, BaseInfoBase::castfn_t *converterTo=0, bool is_virtual=false)
Constructor. converter* and is_virtual are as for add_info.
Definition BaseInfo.cxx:529
bool m_is_virtual
True if the derivation from this base to T is via virtual derivation.
Definition BaseInfo.cxx:48
BaseInfoBase::castfn_t * m_converter
Converter function.
Definition BaseInfo.cxx:39
BaseInfoBase::castfn_t * m_converterTo
Converter function.
Definition BaseInfo.cxx:44
std::lock_guard< mutex_t > lock_t
Definition BaseInfo.cxx:103
BaseInfoBase::destroy_fn * m_destroy
Definition BaseInfo.cxx:99
ti_map_type m_timap
Definition BaseInfo.cxx:66
std::pair< const std::type_info *, const CopyConversionBase * > ti_copyconversion_pair_type
Hold copy conversion information indexed by @ type_info.
Definition BaseInfo.cxx:71
CLID m_clid
CLID of this class.
Definition BaseInfo.cxx:53
ti_copyconversion_type m_ti_copyconversion_map
Definition BaseInfo.cxx:73
static Deleter s_deleter
Definition BaseInfo.cxx:97
std::pair< const std::type_info *, info > ti_map_pair_type
Hold base information indexed by type_info.
Definition BaseInfo.cxx:64
std::vector< ti_copyconversion_pair_type > ti_copyconversion_type
Definition BaseInfo.cxx:72
std::mutex mutex_t
For thread-safety.
Definition BaseInfo.cxx:102
static bi_by_ti_map_type *s_bi_by_ti ATLAS_THREAD_SAFE
Definition BaseInfo.cxx:78
std::unordered_map< std::string, const std::type_info * > ti_by_name_map_type
Used to canonicalize type_info instances.
Definition BaseInfo.cxx:82
CxxUtils::CachedValue< std::vector< CLID > > m_bases
CLIDs of known bases, including the class itself.
Definition BaseInfo.cxx:110
const info * findInfo(const std::type_info &tinfo) const
Find a base by type_info.
Definition BaseInfo.cxx:120
std::vector< ti_map_pair_type > ti_map_type
Definition BaseInfo.cxx:65
std::unordered_multimap< const std::type_info *, BaseInfoBase::init_func_t * > init_list_t
Holds BaseInfo classes awaiting initialization.
Definition BaseInfo.cxx:89
bool m_needs_init
Set to true when first created.
Definition BaseInfo.cxx:57
const std::type_info * m_typeinfo
std::type_info of this class.
Definition BaseInfo.cxx:60
std::unordered_map< const std::type_info *, BaseInfoBase * > bi_by_ti_map_type
Map of all type_info pointers to BaseInfoBase instances.
Definition BaseInfo.cxx:77