Logo ROOT  
Reference Guide
TIsAProxy.cxx
Go to the documentation of this file.
1// @(#)root/meta:$Id$
2// Author: Markus Frank 20/05/2005
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#include "TClass.h"
13#include "TError.h"
14#include "TInterpreter.h"
15#include "TIsAProxy.h"
16
17#include <map>
18#include <type_traits>
19
20/** \class TIsAProxy
21TIsAProxy implementation class.
22*/
23
24namespace {
25 struct DynamicType {
26 // Helper class to enable typeid on any address
27 // Used in code similar to:
28 // typeid( * (DynamicType*) void_ptr );
29 virtual ~DynamicType() {}
30 };
31
32 typedef std::map<const void*, TClass*> ClassMap_t; // Internal type map
33 inline ClassMap_t *GetMap(const void* p)
34 {
35 return (ClassMap_t*)p;
36 }
37
38 inline ClassMap_t::value_type* ToPair(void*p)
39 {
40 return (ClassMap_t::value_type*)p;
41 }
42
43}
44
45////////////////////////////////////////////////////////////////////////////////
46/// Standard initializing constructor
47
48TIsAProxy::TIsAProxy(const std::type_info& typ)
49 : fType(&typ), fClass(nullptr),
50 fSubTypesReaders(0), fSubTypesWriteLockTaken(kFALSE),
51 fInit(kFALSE), fVirtual(kFALSE)
52{
53 static_assert(sizeof(ClassMap_t)<=sizeof(fSubTypes), "ClassMap size is to large for array");
54
55 ::new(fSubTypes) ClassMap_t();
56 for(auto& slot : fLasts)
57 slot = nullptr;
58}
59
60////////////////////////////////////////////////////////////////////////////////
61/// Standard destructor
62
64{
65 ClassMap_t* m = GetMap(fSubTypes);
66 m->clear();
67 m->~ClassMap_t();
68}
69
70////////////////////////////////////////////////////////////////////////////////
71/// Set class pointer
72/// This method is not thread safe
73
75{
76 GetMap(fSubTypes)->clear();
77 fClass = cl;
78 for(auto& slot : fLasts)
79 slot = nullptr;
80}
81
82////////////////////////////////////////////////////////////////////////////////
83/// IsA callback
84
86{
87 if ( !fInit ) {
89 if ( !fClass && fType ) {
91 }
92 if ( !fClass ) return nullptr;
93 fVirtual = (*fClass).ClassProperty() & kClassHasVirtual;
94 fInit = kTRUE;
95 }
96 if ( !obj || !fVirtual ) {
97 return fClass;
98 }
99 // Avoid the case that the first word is a virtual_base_offset_table instead of
100 // a virtual_function_table
101 Long_t offset = **(Long_t**)obj;
102 if ( offset == 0 ) {
103 return fClass;
104 }
105
106 DynamicType* ptr = (DynamicType*)obj;
107 const std::type_info* typ = &typeid(*ptr);
108
109 if ( typ == fType ) {
110 return fClass;
111 }
112 for(auto& slot : fLasts) {
113 auto last = ToPair(slot);
114 if ( last && typ == last->first ) {
115 return last->second;
116 }
117 }
118
119 // Check if type is already in sub-class cache
120 auto last = ToPair(FindSubType(typ));
121 if ( last == nullptr ) {
122 // Last resort: lookup root class
123 auto cls = TClass::GetClass(*typ);
124 if (cls)
125 last = ToPair(CacheSubType(typ,cls));
126 else
127 return nullptr; // Don't record failed searches (a library might be loaded between now and the next search).
128 }
129
130 UChar_t next = fNextLastSlot++;
131 if (next >= fgMaxLastSlot) {
132 UChar_t expected_value = next + 1;
133 next = next % fgMaxLastSlot;
134 fNextLastSlot.compare_exchange_strong(expected_value, next + 1);
135 }
136 fLasts[next].store(last);
137
138 return last ? last->second : nullptr;
139}
140
141////////////////////////////////////////////////////////////////////////////////
142/// See if we have already cached the TClass that correspond to this std::type_info.
143
144inline void* TIsAProxy::FindSubType(const std::type_info* type) const
145{
146 bool needToWait = kTRUE;
147 do {
149
150 //See if there is a writer, if there is we need to release
151 // our reader count so that the writer can proceed
155 } else {
156 needToWait = kFALSE;
157 }
158 } while(needToWait);
159
160 void* returnValue = nullptr;
161 auto const map = GetMap(fSubTypes);
162
163 auto found = map->find(type);
164 if(found != map->end()) {
165 returnValue = &(*found);
166 }
168 return returnValue;
169}
170
171////////////////////////////////////////////////////////////////////////////////
172/// Record the TClass found for a std::type_info, so that we can retrieved it faster.
173
174void* TIsAProxy::CacheSubType(const std::type_info* type, TClass* cls)
175{
176 //See if another thread has the write lock, wait if it does
177 Bool_t expected = kFALSE;
178 while(! fSubTypesWriteLockTaken.compare_exchange_strong(expected,kTRUE) ) {
179 expected = kFALSE;
180 };
181
182 //See if there are any readers
183 while(fSubTypesReaders > 0);
184
185 auto map = GetMap(fSubTypes);
186 auto ret = map->emplace(type,cls);
187 if (!ret.second) {
188 // type is already in the map, let's update it.
189 (*ret.first).second = cls;
190 }
191
193 return &(*(ret.first));
194}
Cppyy::TCppType_t fClass
unsigned char UChar_t
Definition: RtypesCore.h:36
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
bool Bool_t
Definition: RtypesCore.h:61
const Bool_t kTRUE
Definition: RtypesCore.h:89
@ kClassHasVirtual
Definition: TDictionary.h:144
int type
Definition: TGX11.cxx:120
#define R__WRITE_LOCKGUARD(mutex)
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
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:2937
Atomic_t< UInt_t > fSubTypesReaders
Definition: TIsAProxy.h:42
TClass * fClass
Definition: TIsAProxy.h:39
void * CacheSubType(const std::type_info *, TClass *)
Record the TClass found for a std::type_info, so that we can retrieved it faster.
Definition: TIsAProxy.cxx:174
virtual void SetClass(TClass *cl)
Set class pointer This method is not thread safe.
Definition: TIsAProxy.cxx:74
virtual ~TIsAProxy()
Standard destructor.
Definition: TIsAProxy.cxx:63
Atomic_t< UChar_t > fNextLastSlot
Definition: TIsAProxy.h:44
Char_t fSubTypes[72]
Definition: TIsAProxy.h:41
virtual TClass * operator()(const void *obj)
IsA callback.
Definition: TIsAProxy.cxx:85
const std::type_info * fType
Definition: TIsAProxy.h:38
Atomic_t< Bool_t > fSubTypesWriteLockTaken
Definition: TIsAProxy.h:43
Bool_t fVirtual
Definition: TIsAProxy.h:46
Atomic_t< void * > fLasts[fgMaxLastSlot]
Definition: TIsAProxy.h:40
void * FindSubType(const std::type_info *) const
See if we have already cached the TClass that correspond to this std::type_info.
Definition: TIsAProxy.cxx:144
Atomic_t< Bool_t > fInit
Definition: TIsAProxy.h:45
static constexpr UInt_t fgMaxLastSlot
Definition: TIsAProxy.h:36
TIsAProxy(const TIsAProxy &)=delete
R__EXTERN TVirtualRWMutex * gCoreMutex
static constexpr double second
auto * m
Definition: textangle.C:8