ATLAS Offline Software
Loading...
Searching...
No Matches
BaseInfo.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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
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 typedef std::mutex mutex_t;
101 typedef std::lock_guard<mutex_t> lock_t;
102 static mutex_t s_mutex ATLAS_THREAD_SAFE; // For the static variables.
103 mutable mutex_t m_mutex; // For the class members.
104
105
109
110
118 const info* findInfo (const std::type_info& tinfo) const
119 {
120 // We don't expect there to be many entries, so just use a linear search.
121 for (const auto& i : m_timap) {
122 if (i.first == &tinfo)
123 return &i.second;
124 }
125
126 // Sometimes type_info's are not actually unique, depending on how libraries
127 // get loaded. Try again, comparing names.
128 for (const auto& i : m_timap) {
129 if (strcmp (i.first->name(), tinfo.name()) == 0)
130 return &i.second;
131 }
132 return nullptr;
133 }
134};
135
136
137
142{
143 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
144 return m_impl->m_clid;
145}
146
147
151const std::type_info& BaseInfoBase::typeinfo() const
152{
153 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
154 return *m_impl->m_typeinfo;
155}
156
157
166void* BaseInfoBase::cast (void* p, CLID clid) const
167{
168 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
169 if (ti)
170 return this->cast (p, *ti);
171 return 0;
172}
173
174
183void* BaseInfoBase::cast (void* p, const std::type_info& tinfo) const
184{
185 if (BaseInfoBase::castfn_t* converter = castfn (tinfo)) {
186 return converter (p);
187 }
188 return nullptr;
189}
190
191
201void* BaseInfoBase::castTo (void* p, CLID clid) const
202{
203 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
204 if (ti)
205 return this->castTo (p, *ti);
206 return 0;
207}
208
209
219void* BaseInfoBase::castTo (void* p, const std::type_info& tinfo) const
220{
221 if (BaseInfoBase::castfn_t* converterTo = castfnTo (tinfo)) {
222 return converterTo (p);
223 }
224 return nullptr;
225}
226
227
237{
238 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
239 if (ti)
240 return this->castfn (*ti);
241 return 0;
242}
243
244
254BaseInfoBase::castfn (const std::type_info& tinfo) const
255{
256 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
257 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
258 if (i)
259 return i->m_converter;
260 return nullptr;
261}
262
263
273{
274 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
275 if (ti)
276 return this->castfnTo (*ti);
277 return 0;
278}
279
280
290BaseInfoBase::castfnTo (const std::type_info& tinfo) const
291{
292 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
293 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
294 if (i)
295 return i->m_converterTo;
296 return nullptr;
297}
298
299
304const std::vector<CLID>& BaseInfoBase::get_bases() const
305{
306 if (!m_impl->m_bases.isValid()) {
307 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
308 const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
309 std::vector<CLID> v;
310 v.reserve (map.size());
311 for (const auto& p : map) {
313 if (clid != CLID_NULL)
314 v.push_back (clid);
315 }
316 m_impl->m_bases.set (std::move (v));
317 }
318 return *m_impl->m_bases.ptr();
319}
320
321
326std::vector<const std::type_info*> BaseInfoBase::get_ti_bases() const
327{
328 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
329 const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
330 std::vector<const std::type_info*> v;
331 v.reserve (map.size());
332 for (const auto& i : map)
333 v.push_back (i.first);
334 return v;
335}
336
337
345{
346 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
347 if (ti)
348 return this->is_base (*ti);
349 return 0;
350}
351
352
359bool BaseInfoBase::is_base (const std::type_info& tinfo) const
360{
361 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
362 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
363 return i != 0;
364}
365
366
374{
375 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
376 if (ti)
377 return this->is_virtual (*ti);
378 return false;
379}
380
381
388bool BaseInfoBase::is_virtual (const std::type_info& tinfo) const
389{
390 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
391 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
392 if (i)
393 return i->m_is_virtual;
394 return false;
395}
396
397
405BaseInfoBase::copy_conversion (const std::type_info& tinfo) const
406{
407 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
408 for (const auto& p : m_impl->m_ti_copyconversion_map) {
409 if (p.first == &tinfo)
410 return p.second;
411 }
412 return 0;
413}
414
415
424{
425 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
426 if (ti)
427 return this->copy_conversion (*ti);
428 return 0;
429}
430
431
439void
440BaseInfoBase::add_copy_conversion (const std::type_info& tinfo,
441 const CopyConversionBase* cnv)
442{
443 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
444 m_impl->m_ti_copyconversion_map.emplace_back (&tinfo, cnv);
445}
446
447
454std::vector<CLID>
456{
457 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
458 std::vector<CLID> out;
459 out.reserve (m_impl->m_ti_copyconversion_map.size());
460 for (const auto& i : m_impl->m_ti_copyconversion_map) {
462 if (clid != CLID_NULL)
463 out.push_back (clid);
464 }
465 return out;
466}
467
468
479void BaseInfoBase::add_info (const std::type_info& tinfo,
480 castfn_t* converter,
481 castfn_t* converterTo,
482 bool is_virtual)
483{
484 BaseInfoBaseImpl::lock_t slock (BaseInfoBaseImpl::s_mutex);
485 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
486 {
487 const BaseInfoBaseImpl::info* i = m_impl->findInfo (tinfo);
488 if (!i) {
489 m_impl->m_timap.emplace_back (&tinfo,
490 BaseInfoBaseImpl::info (converter, converterTo, is_virtual));
491 }
492 }
493
494 auto i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
495 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
496 BaseInfoBaseImpl& impl = *i->second->m_impl;
497 if (impl.m_clid == CLID_NULL)
498 impl.m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
499 }
500}
501
502
516 BaseInfoBase::castfn_t* converterTo /*= 0*/,
517 bool is_virtual /*= false*/)
518 : m_converter (converter),
519 m_converterTo (converterTo),
520 m_is_virtual (is_virtual)
521{
522}
523
524
529BaseInfoBase::BaseInfoBase (const std::type_info& tinfo)
531{
532 m_impl->m_clid = CLIDRegistry::typeinfoToCLID (tinfo);
533 m_impl->m_typeinfo = &tinfo;
534 m_impl->m_needs_init = true;
535
536 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
537 if (!BaseInfoBaseImpl::s_bi_by_ti)
538 BaseInfoBaseImpl::s_bi_by_ti = new BaseInfoBaseImpl::bi_by_ti_map_type;
539 if (!BaseInfoBaseImpl::s_ti_by_name)
540 BaseInfoBaseImpl::s_ti_by_name = new BaseInfoBaseImpl::ti_by_name_map_type;
541
542 // Register this instance in the static maps.
543 (*BaseInfoBaseImpl::s_bi_by_ti)[&tinfo] = this;
544 (*BaseInfoBaseImpl::s_ti_by_name)[tinfo.name()] = &tinfo;
545}
546
547
552{
553 for (BaseInfoBaseImpl::ti_copyconversion_type::iterator it =
554 m_impl->m_ti_copyconversion_map.begin();
555 it != m_impl->m_ti_copyconversion_map.end();
556 ++it)
557 {
558 delete it->second;
559 }
560 delete m_impl;
561}
562
563
571{
572 const std::type_info* ti = CLIDRegistry::CLIDToTypeinfo (clid);
573 if (ti)
574 return BaseInfoBase::find (*ti);
575 return 0;
576}
577
578
586BaseInfoBase* BaseInfoBase::find1 (const std::type_info& tinfo)
587{
588 BaseInfoBase* bib = nullptr;
589 {
590 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
591 if (!BaseInfoBaseImpl::s_bi_by_ti) return 0;
592 BaseInfoBaseImpl::bi_by_ti_map_type::iterator i =
593 BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
594 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
595 bib = i->second;
597 if (!bib->m_impl->m_needs_init)
598 return bib;
599 bib->m_impl->m_needs_init = false;
600 }
601 }
602
603 // Try the initlist.
604 while (true) {
605 BaseInfoBase::init_func_t* init = nullptr;
606 {
607 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
608 if (!BaseInfoBaseImpl::s_init_list) break;
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;
613 BaseInfoBaseImpl::init_list_t::iterator it =
614 BaseInfoBaseImpl::s_init_list->find (&tinfo);
615 if (it == BaseInfoBaseImpl::s_init_list->end()) break;
616 init = it->second;
617 BaseInfoBaseImpl::s_init_list->erase (it);
618 }
619 init (bib);
620 }
621
622 return bib;
623}
624
625
633const BaseInfoBase* BaseInfoBase::find (const std::type_info& tinfo)
634{
635 BaseInfoBase* bib = find1 (tinfo);
636
637 // If we didn't find it, try looking up by name.
638 // This to deal with the issue of sometimes getting duplicate
639 // @c std::type_info instances.
640 if (!bib) {
641 const std::type_info* tinfo2 = nullptr;
642 {
643 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
644 if (BaseInfoBaseImpl::s_ti_by_name) {
645 BaseInfoBaseImpl::ti_by_name_map_type::iterator i =
646 BaseInfoBaseImpl::s_ti_by_name->find (tinfo.name());
647 if (i != BaseInfoBaseImpl::s_ti_by_name->end() && i->second != &tinfo) {
648 tinfo2 = i->second;
649 }
650 }
651 }
652 if (tinfo2) {
653 bib = find1 (*tinfo2);
654 }
655 }
656
657 if (bib) {
659 BaseInfoBaseImpl::lock_t lock (impl.m_mutex);
660 if (impl.m_clid == CLID_NULL)
661 impl.m_clid = CLIDRegistry::typeinfoToCLID (*impl.m_typeinfo);
662 }
663
664 return bib;
665}
666
667
673void BaseInfoBase::addInit (const std::type_info* tinfo,
674 init_func_t* init_func)
675{
676 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
677 if (!BaseInfoBaseImpl::s_init_list)
678 BaseInfoBaseImpl::s_init_list =
680 BaseInfoBaseImpl::s_init_list->insert (std::make_pair (tinfo, init_func));
681
682 if (BaseInfoBaseImpl::s_bi_by_ti) {
683 auto i = BaseInfoBaseImpl::s_bi_by_ti->find (tinfo);
684 if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
685 BaseInfoBaseImpl::lock_t lock (i->second->m_impl->m_mutex);
686 BaseInfoBaseImpl& impl = *i->second->m_impl;
687 impl.m_needs_init = true;
688 if (impl.m_clid == CLID_NULL)
689 impl.m_clid = CLIDRegistry::typeinfoToCLID (*tinfo);
690 }
691 }
692}
693
694
699{
700 // This may be null during initialization, if we're initializing a
701 // BaseInfo<T>::s_instance instance which references another type
702 // for which the s_instance constructor has not yet been run.
703 if (!m_impl) return;
704
705 bool needs_init = false;
706 const std::type_info* ti = nullptr;
707 {
708 BaseInfoBaseImpl::lock_t lock (m_impl->m_mutex);
709 needs_init = m_impl->m_needs_init;
710 ti = m_impl->m_typeinfo;
711 }
712
713 if (needs_init)
714 find (*ti);
715}
716
717
718
720BaseInfoBaseImpl::bi_by_ti_map_type* BaseInfoBaseImpl::s_bi_by_ti = 0;
721BaseInfoBaseImpl::ti_by_name_map_type* BaseInfoBaseImpl::s_ti_by_name = 0;
722BaseInfoBaseImpl::init_list_t* BaseInfoBaseImpl::s_init_list = 0;
723BaseInfoBaseImpl::mutex_t BaseInfoBaseImpl::s_mutex;
724
725// To get them deleted.
728{
729 delete s_bi_by_ti;
730 delete s_ti_by_name;
731 delete s_init_list;
732}
733
734
735// Helper for dumping within the debugger.
737{
738 BaseInfoBaseImpl::lock_t lock (BaseInfoBaseImpl::s_mutex);
739 std::cout << "map:\n";
740 if (BaseInfoBaseImpl::s_bi_by_ti) {
741 std::vector<const std::type_info*> vv;
742 for (const auto& x : *BaseInfoBaseImpl::s_bi_by_ti)
743 vv.push_back (x.first);
744 std::sort (vv.begin(), vv.end());
745 for (const std::type_info* ti : vv)
746 {
747 const BaseInfoBase* bib = (*BaseInfoBaseImpl::s_bi_by_ti)[ti];
748 std::cout << ti << " " << bib->clid() << " [" << System::typeinfoName (*ti)
749 << "]\n";
750 }
751 }
752
753 std::cout << "\ninitlist:\n";
754 if (BaseInfoBaseImpl::s_init_list) {
755 for (const auto& x : *BaseInfoBaseImpl::s_init_list)
756 std::cout << x.first << " " << x.second << " ["
757 << System::typeinfoName (*x.first) << "]\n";
758 }
759}
760
761
762} // 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:586
const CopyConversionBase * copy_conversion(const std::type_info &tinfo) const
Search for a copy conversion to tinfo.
Definition BaseInfo.cxx:405
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:479
void add_copy_conversion(const std::type_info &tinfo, const CopyConversionBase *cnv)
Add a new copy conversion.
Definition BaseInfo.cxx:440
void maybeInit()
Run initializations for this class, if needed.
Definition BaseInfo.cxx:698
void init_func_t(BaseInfoBase *bib)
Type for an initialization function.
~BaseInfoBase()
Destructor.
Definition BaseInfo.cxx:551
std::vector< const std::type_info * > get_ti_bases() const
Return the type_info's of all known bases of T.
Definition BaseInfo.cxx:326
castfn_t * castfnTo(CLID clid) const
Return a function for casting to a derived pointer.
Definition BaseInfo.cxx:272
void * castTo(void *p, CLID clid) const
Cast to a derived pointer.
Definition BaseInfo.cxx:201
CLID clid() const
Return the CLID for this class.
Definition BaseInfo.cxx:141
static void addInit(const std::type_info *tinfo, init_func_t *init_func)
Register an initialization function.
Definition BaseInfo.cxx:673
static const BaseInfoBase * find(CLID clid)
Find the BaseInfoBase instance for clid.
Definition BaseInfo.cxx:570
const std::type_info & typeinfo() const
Return the std::type_info for this class.
Definition BaseInfo.cxx:151
void * cast(void *p, CLID clid) const
Cast to a base pointer.
Definition BaseInfo.cxx:166
BaseInfoBase(const std::type_info &tinfo)
Constructor.
Definition BaseInfo.cxx:529
castfn_t * castfn(CLID clid) const
Return a function for casting to a base pointer.
Definition BaseInfo.cxx:236
const std::vector< CLID > & get_bases() const
Return the class IDs of all known bases of T (that have class IDs).
Definition BaseInfo.cxx:304
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:344
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:373
std::vector< CLID > get_copy_conversions() const
Return known copy conversions.
Definition BaseInfo.cxx:455
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:736
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:515
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:101
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:100
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:108
const info * findInfo(const std::type_info &tinfo) const
Find a base by type_info.
Definition BaseInfo.cxx:118
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