diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h index f584ab02a95d9..277551b38d5fe 100644 --- a/core/meta/inc/TClass.h +++ b/core/meta/inc/TClass.h @@ -149,7 +149,11 @@ friend class ROOT::TGenericClassInfo; TVirtualIsAProxy *fIsA; //!pointer to the class's IsA proxy. IsAGlobalFunc_t fGlobalIsA; //pointer to a global IsA function. +#if __cplusplus > 199711L + mutable std::atomic fIsAMethod; //!saved info to call a IsA member function +#else mutable TMethodCall *fIsAMethod; //!saved info to call a IsA member function +#endif ROOT::MergeFunc_t fMerge; //pointer to a function implementing Merging objects of this class. ROOT::ResetAfterMergeFunc_t fResetAfterMerge; //pointer to a function implementing Merging objects of this class. diff --git a/core/meta/src/TClass.cxx b/core/meta/src/TClass.cxx index 303b41c796b4b..2e5fff23d74b9 100644 --- a/core/meta/src/TClass.cxx +++ b/core/meta/src/TClass.cxx @@ -1197,7 +1197,7 @@ TClass::TClass(const TClass& cl) : fSharedLibs(cl.fSharedLibs), fIsA(cl.fIsA), fGlobalIsA(cl.fGlobalIsA), - fIsAMethod(cl.fIsAMethod), + fIsAMethod(0), fMerge(cl.fMerge), fResetAfterMerge(cl.fResetAfterMerge), fNew(cl.fNew), @@ -1326,7 +1326,11 @@ TClass::~TClass() delete fStreamer; delete fCollectionProxy; +#if __cplusplus > 199711L + delete fIsAMethod.load(); +#else delete fIsAMethod; +#endif delete fSchemaRules; if (fConversionStreamerInfo) { std::map::iterator it; @@ -2268,18 +2272,28 @@ TClass *TClass::GetActualClass(const void *object) const //will not work if the class derives from TObject but not as primary //inheritance. if (fIsAMethod==0) { - fIsAMethod = new TMethodCall((TClass*)this, "IsA", ""); + TMethodCall* temp = new TMethodCall((TClass*)this, "IsA", ""); - if (!fIsAMethod->GetMethod()) { - delete fIsAMethod; - fIsAMethod = 0; + if (!temp->GetMethod()) { + delete temp; Error("IsA","Can not find any IsA function for %s!",GetName()); return (TClass*)this; } - +#if __cplusplus > 199711L + //Force cache to be updated here so do not have to worry about concurrency + temp->ReturnType(); + + TMethodCall* expected = nullptr; + if( not fIsAMethod.compare_exchange_strong(expected,temp) ) { + //another thread beat us to it + delete temp; + } +#else + fIsAMethod = temp; +#endif } char * char_result = 0; - fIsAMethod->Execute((void*)object, &char_result); + (*fIsAMethod).Execute((void*)object, &char_result); return (TClass*)char_result; } }