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 <print>
24#include "string.h"
25
26
27namespace SG {
28
29
32 struct info {
34 info (BaseInfoBase::castfn_t* converter = 0,
35 BaseInfoBase::castfn_t* converterTo = 0,
36 bool is_virtual = false);
37
41
46
50 };
51
52
55
58 bool m_needs_init{true};
59
61 const std::type_info* m_typeinfo{};
62
63
65 typedef std::pair<const std::type_info*, info> ti_map_pair_type;
66 typedef std::vector<ti_map_pair_type> ti_map_type;
68
69
71 typedef std::pair<const std::type_info*, const CopyConversionBase*>
73 typedef std::vector<ti_copyconversion_pair_type> ti_copyconversion_type;
75
76
78 typedef std::unordered_map<const std::type_info*, BaseInfoBase*> bi_by_ti_map_type;
80
81
83 typedef std::unordered_map<std::string, const std::type_info*> ti_by_name_map_type;
85
86
89 typedef std::unordered_multimap<const std::type_info*,
91 static init_list_t* s_init_list ATLAS_THREAD_SAFE;
92
93
94 // To make sure that the maps get deleted at program termination.
95 struct Deleter {
96 ~Deleter();
97 };
99
101
103 typedef std::mutex mutex_t;
104 typedef std::lock_guard<mutex_t> lock_t;
105 static mutex_t s_mutex ATLAS_THREAD_SAFE; // For the static variables.
106 mutable mutex_t m_mutex; // For the class members.
107
108
112
113
121 const info* findInfo (const std::type_info& tinfo) const
122 {
123 // We don't expect there to be many entries, so just use a linear search.
124 for (const auto& i : m_timap) {
125 if (i.first == &tinfo)
126 return &i.second;
127 }
128
129 // Sometimes type_info's are not actually unique, depending on how libraries
130 // get loaded. Try again, comparing names.
131 for (const auto& i : m_timap) {
132 if (strcmp (i.first->name(), tinfo.name()) == 0)
133 return &i.second;
134 }
135 return nullptr;
136 }
137};
138
139
140
145{
147 return m_impl->m_clid;
148}
149
150
154const std::type_info& BaseInfoBase::typeinfo() const
155{
157 return *m_impl->m_typeinfo;
158}
159
160
169void* BaseInfoBase::cast (void* p, CLID clid) const
170{
171 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
172 if (ti)
173 return this->cast (p, *ti);
174 return 0;
175}
176
177
186void* BaseInfoBase::cast (void* p, const std::type_info& tinfo) const
187{
188 if (BaseInfoBase::castfn_t* converter = castfn (tinfo)) {
189 return converter (p);
190 }
191 return nullptr;
192}
193
194
204void* BaseInfoBase::castTo (void* p, CLID clid) const
205{
206 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
207 if (ti)
208 return this->castTo (p, *ti);
209 return 0;
210}
211
212
222void* BaseInfoBase::castTo (void* p, const std::type_info& tinfo) const
223{
224 if (BaseInfoBase::castfn_t* converterTo = castfnTo (tinfo)) {
225 return converterTo (p);
226 }
227 return nullptr;
228}
229
230
240{
241 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
242 if (ti)
243 return this->castfn (*ti);
244 return 0;
245}
246
247
257BaseInfoBase::castfn (const std::type_info& tinfo) const
258{
260 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
261 if (i)
262 return i->m_converter;
263 return nullptr;
264}
265
266
276{
277 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
278 if (ti)
279 return this->castfnTo (*ti);
280 return 0;
281}
282
283
293BaseInfoBase::castfnTo (const std::type_info& tinfo) const
294{
296 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
297 if (i)
298 return i->m_converterTo;
299 return nullptr;
300}
301
302
307const std::vector<CLID>& BaseInfoBase::get_bases() const
308{
309 if (!m_impl->m_bases.isValid()) {
311 const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
312 std::vector<CLID> v;
313 v.reserve (map.size());
314 for (const auto& p : map) {
316 if (clid != CLID_NULL)
317 v.push_back (clid);
318 }
319 m_impl->m_bases.set (std::move (v));
320 }
321 return *m_impl->m_bases.ptr();
322}
323
324
329std::vector<const std::type_info*> BaseInfoBase::get_ti_bases() const
330{
332 const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
333 std::vector<const std::type_info*> v;
334 v.reserve (map.size());
335 for (const auto& i : map)
336 v.push_back (i.first);
337 return v;
338}
339
340
348{
349 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
350 if (ti)
351 return this->is_base (*ti);
352 return 0;
353}
354
355
362bool BaseInfoBase::is_base (const std::type_info& tinfo) const
363{
365 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
366 return i != 0;
367}
368
369
377{
378 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
379 if (ti)
380 return this->is_virtual (*ti);
381 return false;
382}
383
384
391bool BaseInfoBase::is_virtual (const std::type_info& tinfo) const
392{
394 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
395 if (i)
396 return i->m_is_virtual;
397 return false;
398}
399
400
408BaseInfoBase::copy_conversion (const std::type_info& tinfo) const
409{
411 for (const auto& p : m_impl->m_ti_copyconversion_map) {
412 if (p.first == &tinfo)
413 return p.second;
414 }
415 return 0;
416}
417
418
427{
428 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
429 if (ti)
430 return this->copy_conversion (*ti);
431 return 0;
432}
433
434
439void BaseInfoBase::destroy (void* p) const
440{
442 if (m_impl->m_destroy)
443 m_impl->m_destroy (p);
444}
445
446
454void
455BaseInfoBase::add_copy_conversion (const std::type_info& tinfo,
456 const CopyConversionBase* cnv)
457{
459 m_impl->m_ti_copyconversion_map.emplace_back (&tinfo, cnv);
460}
461
462
469std::vector<CLID>
471{
473 std::vector<CLID> out;
474 out.reserve (m_impl->m_ti_copyconversion_map.size());
475 for (const auto& i : m_impl->m_ti_copyconversion_map) {
477 if (clid != CLID_NULL)
478 out.push_back (clid);
479 }
480 return out;
481}
482
483
494void BaseInfoBase::add_info (const std::type_info& tinfo,
495 castfn_t* converter,
496 castfn_t* converterTo,
497 bool is_virtual)
498{
499 BaseInfoBaseImpl::lock_t slock (BaseInfoBaseImpl::s_mutex);
501 {
502 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
503 if (!i) {
504 m_impl->m_timap.emplace_back (&tinfo,
505 BaseInfoBaseImpl::info (converter, converterTo, is_virtual));
506 }
507 }
508
509 auto i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
510 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
511 BaseInfoBaseImpl& impl = *i->second->m_impl;
512 if (impl.m_clid == CLID_NULL)
513 impl.m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
514 }
515}
516
517
531 BaseInfoBase::castfn_t* converterTo /*= 0*/,
532 bool is_virtual /*= false*/)
533 : m_converter (converter),
534 m_converterTo (converterTo),
535 m_is_virtual (is_virtual)
536{
537}
538
539
544BaseInfoBase::BaseInfoBase (const std::type_info& tinfo,
547{
548 m_impl->m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
549 m_impl->m_typeinfo = &tinfo;
550 m_impl->m_destroy = destroy;
551 m_impl->m_needs_init = true;
552
553 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
554 if (!BaseInfoBaseImpl::s_bi_by_ti)
555 BaseInfoBaseImpl::s_bi_by_ti = new BaseInfoBaseImpl::bi_by_ti_map_type;
556 if (!BaseInfoBaseImpl::s_ti_by_name)
557 BaseInfoBaseImpl::s_ti_by_name = new BaseInfoBaseImpl::ti_by_name_map_type;
558
559 // Register this instance in the static maps.
560 (*BaseInfoBaseImpl::s_bi_by_ti)[&tinfo] = this;
561 (*BaseInfoBaseImpl::s_ti_by_name)[tinfo.name()] = &tinfo;
562}
563
564
569{
570 for (BaseInfoBaseImpl::ti_copyconversion_type::iterator it =
571 m_impl->m_ti_copyconversion_map.begin();
572 it != m_impl->m_ti_copyconversion_map.end();
573 ++it)
574 {
575 delete it->second;
576 }
577 delete m_impl;
578}
579
580
588{
589 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
590 if (ti)
591 return BaseInfoBase::find (*ti);
592 return 0;
593}
594
595
603BaseInfoBase* BaseInfoBase::find1 (const std::type_info& tinfo)
604{
605 BaseInfoBase* bib = nullptr;
606 {
607 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
608 if (!BaseInfoBaseImpl::s_bi_by_ti) return 0;
609 BaseInfoBaseImpl::bi_by_ti_map_type::iterator i =
610 BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
611 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
612 bib = i->second;
614 if (!bib->m_impl->m_needs_init)
615 return bib;
616 bib->m_impl->m_needs_init = false;
617 }
618 }
619
620 // Try the initlist.
621 while (true) {
622 BaseInfoBase::init_func_t* init = nullptr;
623 {
624 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
625 if (!BaseInfoBaseImpl::s_init_list) break;
626 BaseInfoBaseImpl::bi_by_ti_map_type::iterator i =
627 BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
628 if (i != BaseInfoBaseImpl::s_bi_by_ti->end())
629 bib = i->second;
630 BaseInfoBaseImpl::init_list_t::iterator it =
631 BaseInfoBaseImpl::s_init_list->find (&tinfo);
632 if (it == BaseInfoBaseImpl::s_init_list->end()) break;
633 init = it->second;
634 BaseInfoBaseImpl::s_init_list->erase (it);
635 }
636 init (bib);
637 }
638
639 return bib;
640}
641
642
650const BaseInfoBase* BaseInfoBase::find (const std::type_info& tinfo)
651{
652 BaseInfoBase* bib = find1 (tinfo);
653
654 // If we didn't find it, try looking up by name.
655 // This to deal with the issue of sometimes getting duplicate
656 // @c std::type_info instances.
657 if (!bib) {
658 const std::type_info* tinfo2 = nullptr;
659 {
660 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
661 if (BaseInfoBaseImpl::s_ti_by_name) {
662 BaseInfoBaseImpl::ti_by_name_map_type::iterator i =
663 BaseInfoBaseImpl::s_ti_by_name->find (tinfo.name());
664 if (i != BaseInfoBaseImpl::s_ti_by_name->end() && i->second != &tinfo) {
665 tinfo2 = i->second;
666 }
667 }
668 }
669 if (tinfo2) {
670 bib = find1 (*tinfo2);
671 }
672 }
673
674 if (bib) {
677 if (impl.m_clid == CLID_NULL)
678 impl.m_clid = CLIDRegistry::typeinfoToCLID (*impl.m_typeinfo);
679 }
680
681 return bib;
682}
683
684
690void BaseInfoBase::addInit (const std::type_info* tinfo,
691 init_func_t* init_func)
692{
693 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
694 if (!BaseInfoBaseImpl::s_init_list)
695 BaseInfoBaseImpl::s_init_list =
697 BaseInfoBaseImpl::s_init_list->insert (std::make_pair (tinfo, init_func));
698
699 if (BaseInfoBaseImpl::s_bi_by_ti) {
700 auto i = BaseInfoBaseImpl::s_bi_by_ti->find (tinfo);
701 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
702 BaseInfoBaseImpl::lock_t lock (i->second->m_impl->m_mutex);
703 BaseInfoBaseImpl& impl = *i->second->m_impl;
704 impl.m_needs_init = true;
705 if (impl.m_clid == CLID_NULL)
706 impl.m_clid = CLIDRegistry::typeinfoToCLID (*tinfo);
707 }
708 }
709}
710
711
716{
717 // This may be null during initialization, if we're initializing a
718 // BaseInfo<T>::s_instance instance which references another type
719 // for which the s_instance constructor has not yet been run.
720 if (!m_impl) return;
721
722 bool needs_init = false;
723 const std::type_info* ti = nullptr;
724 {
726 needs_init = m_impl->m_needs_init;
727 ti = m_impl->m_typeinfo;
728 }
729
730 if (needs_init)
731 find (*ti);
732}
733
734
735
737BaseInfoBaseImpl::bi_by_ti_map_type* BaseInfoBaseImpl::s_bi_by_ti = 0;
738BaseInfoBaseImpl::ti_by_name_map_type* BaseInfoBaseImpl::s_ti_by_name = 0;
739BaseInfoBaseImpl::init_list_t* BaseInfoBaseImpl::s_init_list = 0;
740BaseInfoBaseImpl::mutex_t BaseInfoBaseImpl::s_mutex;
741
742// To get them deleted.
745{
746 delete s_bi_by_ti;
747 delete s_ti_by_name;
748 delete s_init_list;
749}
750
751
752// Helper for dumping within the debugger.
754{
755 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
756 std::println ("map:");
757 if (BaseInfoBaseImpl::s_bi_by_ti) {
758 std::vector<const std::type_info*> vv;
759 for (const auto& x : *BaseInfoBaseImpl::s_bi_by_ti)
760 vv.push_back (x.first);
761 std::sort (vv.begin(), vv.end());
762 for (const std::type_info* ti : vv)
763 {
764 const BaseInfoBase* bib = (*BaseInfoBaseImpl::s_bi_by_ti)[ti];
765 std::println ("{} {} [{}]",
766 static_cast<const void*>(ti),
767 bib->clid(), System::typeinfoName (*ti));
768 }
769 }
770
771 std::println ("\ninitlist:");
772 if (BaseInfoBaseImpl::s_init_list) {
773 for (const auto& x : *BaseInfoBaseImpl::s_init_list)
774 std::println ("{} {} [{}]",
775 static_cast<const void*>(x.first),
776 reinterpret_cast<const void*>(x.second),
777 System::typeinfoName (*x.first));
778 }
779}
780
781
782} // 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:603
BaseInfoBase(const std::type_info &tinfo, destroy_fn *destroy)
Constructor.
Definition BaseInfo.cxx:544
const CopyConversionBase * copy_conversion(const std::type_info &tinfo) const
Search for a copy conversion to tinfo.
Definition BaseInfo.cxx:408
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:494
void add_copy_conversion(const std::type_info &tinfo, const CopyConversionBase *cnv)
Add a new copy conversion.
Definition BaseInfo.cxx:455
void maybeInit()
Run initializations for this class, if needed.
Definition BaseInfo.cxx:715
void init_func_t(BaseInfoBase *bib)
Type for an initialization function.
~BaseInfoBase()
Destructor.
Definition BaseInfo.cxx:568
std::vector< const std::type_info * > get_ti_bases() const
Return the type_info's of all known bases of T.
Definition BaseInfo.cxx:329
castfn_t * castfnTo(CLID clid) const
Return a function for casting to a derived pointer.
Definition BaseInfo.cxx:275
void * castTo(void *p, CLID clid) const
Cast to a derived pointer.
Definition BaseInfo.cxx:204
CLID clid() const
Return the CLID for this class.
Definition BaseInfo.cxx:144
static void addInit(const std::type_info *tinfo, init_func_t *init_func)
Register an initialization function.
Definition BaseInfo.cxx:690
void destroy(void *p) const
Delete an instance of the described type.
Definition BaseInfo.cxx:439
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition BaseInfo.cxx:587
const std::type_info & typeinfo() const
Return the std::type_info for this class.
Definition BaseInfo.cxx:154
void * cast(void *p, CLID clid) const
Cast to a base pointer.
Definition BaseInfo.cxx:169
castfn_t * castfn(CLID clid) const
Return a function for casting to a base pointer.
Definition BaseInfo.cxx:239
const std::vector< CLID > & get_bases() const
Return the class IDs of all known bases of T (that have class IDs).
Definition BaseInfo.cxx:307
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:347
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:376
std::vector< CLID > get_copy_conversions() const
Return known copy conversions.
Definition BaseInfo.cxx:470
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:753
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:32
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:530
bool m_is_virtual
True if the derivation from this base to T is via virtual derivation.
Definition BaseInfo.cxx:49
BaseInfoBase::castfn_t * m_converter
Converter function.
Definition BaseInfo.cxx:40
BaseInfoBase::castfn_t * m_converterTo
Converter function.
Definition BaseInfo.cxx:45
std::lock_guard< mutex_t > lock_t
Definition BaseInfo.cxx:104
BaseInfoBase::destroy_fn * m_destroy
Definition BaseInfo.cxx:100
ti_map_type m_timap
Definition BaseInfo.cxx:67
std::pair< const std::type_info *, const CopyConversionBase * > ti_copyconversion_pair_type
Hold copy conversion information indexed by @ type_info.
Definition BaseInfo.cxx:72
CLID m_clid
CLID of this class.
Definition BaseInfo.cxx:54
ti_copyconversion_type m_ti_copyconversion_map
Definition BaseInfo.cxx:74
static Deleter s_deleter
Definition BaseInfo.cxx:98
std::pair< const std::type_info *, info > ti_map_pair_type
Hold base information indexed by type_info.
Definition BaseInfo.cxx:65
std::vector< ti_copyconversion_pair_type > ti_copyconversion_type
Definition BaseInfo.cxx:73
std::mutex mutex_t
For thread-safety.
Definition BaseInfo.cxx:103
static bi_by_ti_map_type *s_bi_by_ti ATLAS_THREAD_SAFE
Definition BaseInfo.cxx:79
std::unordered_map< std::string, const std::type_info * > ti_by_name_map_type
Used to canonicalize type_info instances.
Definition BaseInfo.cxx:83
CxxUtils::CachedValue< std::vector< CLID > > m_bases
CLIDs of known bases, including the class itself.
Definition BaseInfo.cxx:111
const info * findInfo(const std::type_info &tinfo) const
Find a base by type_info.
Definition BaseInfo.cxx:121
std::vector< ti_map_pair_type > ti_map_type
Definition BaseInfo.cxx:66
std::unordered_multimap< const std::type_info *, BaseInfoBase::init_func_t * > init_list_t
Holds BaseInfo classes awaiting initialization.
Definition BaseInfo.cxx:90
bool m_needs_init
Set to true when first created.
Definition BaseInfo.cxx:58
const std::type_info * m_typeinfo
std::type_info of this class.
Definition BaseInfo.cxx:61
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:78