From 9dc3c03513bcbf5160480a0915ef28ed50954ed3 Mon Sep 17 00:00:00 2001 From: Danilo Piparo <danilo.piparo@cern.ch> Date: Wed, 16 Jan 2019 16:43:43 +0100 Subject: [PATCH] [Core] Add TClass::GetClass<T> method to lower contention The method TClass::GetClass<T> obtains the TClass instance pointer corresponding to T in two ways, according to the nature of T. If T inherits from or is TObject, the TClass* value is obtained via the T::Class() static method, which locks only upon the first call. If T is a generic type, internally the TClass::GetClass(type_info, ...) method is called. The new functionality is put to a good use by this commit in TBuffer and TDirectoryFile. It is worth noting how the usage of tag dispatching could be replaced by 'if constexpr'. --- core/base/inc/TBuffer.h | 14 ++++---------- core/meta/inc/TClass.h | 26 ++++++++++++++++++++++++++ io/io/inc/TDirectoryFile.h | 2 +- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/core/base/inc/TBuffer.h b/core/base/inc/TBuffer.h index e764da8d9ab..d7470de3098 100644 --- a/core/base/inc/TBuffer.h +++ b/core/base/inc/TBuffer.h @@ -22,12 +22,12 @@ ////////////////////////////////////////////////////////////////////////// #include "TObject.h" +#include "TClass.h" #include <vector> class TVirtualStreamerInfo; class TStreamerElement; -class TClass; class TString; class TProcessID; class TClonesArray; @@ -386,14 +386,14 @@ template <class Tmpl> TBuffer &operator>>(TBuffer &buf, Tmpl *&obj) // would not be sufficient to pass the information 'which class do we want' // since the pointer could be zero (so typeid(*obj) is not usable). - TClass *cl = TBuffer::GetClass(typeid(Tmpl)); + auto cl = TClass::GetClass<Tmpl>(); obj = (Tmpl *) ( (void*) buf.ReadObjectAny(cl) ); return buf; } template <class Tmpl> TBuffer &operator<<(TBuffer &buf, const Tmpl *obj) { - TClass *cl = (obj) ? TBuffer::GetClass(typeid(*obj)) : 0; + auto cl = (obj) ? TClass::GetClass<Tmpl>() : nullptr; buf.WriteObjectAny(obj, cl); return buf; } @@ -402,16 +402,10 @@ template <class Tmpl> TBuffer &operator>>(TBuffer &buf, Tmpl *&obj); template <class Tmpl> TBuffer &operator<<(TBuffer &buf, Tmpl *&obj); #endif -#if defined(R__TEMPLATE_OVERLOAD_BUG) -template <> -#endif -inline TBuffer &operator<<(TBuffer &buf, const TObject *obj) - { buf.WriteObjectAny(obj, TObject::Class()); return buf; } - template <class T> inline Int_t TBuffer::WriteObject(const T *objptr, Bool_t cacheReuse) { - TClass *cl = (objptr) ? TBuffer::GetClass(typeid(T)) : 0; + auto cl = (objptr) ? TClass::GetClass<T>() : nullptr; return WriteObjectAny(objptr, cl, cacheReuse); } diff --git a/core/meta/inc/TClass.h b/core/meta/inc/TClass.h index be1c4d88b48..825f2fddccd 100644 --- a/core/meta/inc/TClass.h +++ b/core/meta/inc/TClass.h @@ -539,6 +539,8 @@ public: static TClass *GetClass(const char *name, Bool_t load = kTRUE, Bool_t silent = kFALSE); static TClass *GetClass(const std::type_info &typeinfo, Bool_t load = kTRUE, Bool_t silent = kFALSE); static TClass *GetClass(ClassInfo_t *info, Bool_t load = kTRUE, Bool_t silent = kFALSE); + template<typename T> + static TClass *GetClass(Bool_t load = kTRUE, Bool_t silent = kFALSE); static Bool_t GetClass(DeclId_t id, std::vector<TClass*> &classes); static DictFuncPtr_t GetDict (const char *cname); static DictFuncPtr_t GetDict (const std::type_info &info); @@ -572,6 +574,30 @@ public: ClassDef(TClass,0) //Dictionary containing class information }; +namespace ROOT { +namespace Internal { +template <typename T> +TClass *GetClassHelper(Bool_t, Bool_t, std::true_type) +{ + return T::Class(); +} + +template <typename T> +TClass *GetClassHelper(Bool_t load, Bool_t silent, std::false_type) +{ + return TClass::GetClass(typeid(T), load, silent); +} + +} // namespace Internal +} // namespace ROOT + +template <typename T> +TClass *TClass::GetClass(Bool_t load, Bool_t silent) +{ + typename std::is_base_of<TObject, T>::type tag; + return ROOT::Internal::GetClassHelper<T>(load, silent, tag); +} + namespace ROOT { template <typename T> TClass *GetClass(T * /* dummy */) { return TClass::GetClass(typeid(T)); } diff --git a/io/io/inc/TDirectoryFile.h b/io/io/inc/TDirectoryFile.h index 919a0dec6a0..81e3b82f0e0 100644 --- a/io/io/inc/TDirectoryFile.h +++ b/io/io/inc/TDirectoryFile.h @@ -78,7 +78,7 @@ public: virtual TDirectory *GetDirectory(const char *apath, Bool_t printError = false, const char *funcname = "GetDirectory"); template <class T> inline void GetObject(const char* namecycle, T*& ptr) // See TDirectory::Get for information { - ptr = (T*)GetObjectChecked(namecycle,TBuffer::GetClass(typeid(T))); + ptr = (T*)GetObjectChecked(namecycle,TClass::GetClass<T>()); } virtual void *GetObjectChecked(const char *namecycle, const char* classname); virtual void *GetObjectChecked(const char *namecycle, const TClass* cl); -- GitLab