From f0e07fa1f0181a6f7a41e8ff4baf46e2c9c85900 Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Fri, 14 Jul 2017 22:20:14 +0200 Subject: [PATCH] First attempt to make ObjectExtension instances persistent in ROOT --- .../include/DDAlign/GlobalAlignmentCache.h | 2 + DDAlign/src/GlobalAlignmentCache.cpp | 4 +- DDCore/include/DD4hep/DetElement.h | 23 +++--- DDCore/include/DD4hep/Detector.h | 9 ++- DDCore/include/DD4hep/ExtensionEntry.h | 77 ++++++++++++------- DDCore/src/ExtensionEntry.cpp | 2 +- DDCore/src/ObjectExtensions.cpp | 4 +- DDG4/include/DDG4/Geant4Context.h | 8 +- 8 files changed, 79 insertions(+), 50 deletions(-) diff --git a/DDAlign/include/DDAlign/GlobalAlignmentCache.h b/DDAlign/include/DDAlign/GlobalAlignmentCache.h index fe4ac1d53..6e8bbcd85 100644 --- a/DDAlign/include/DDAlign/GlobalAlignmentCache.h +++ b/DDAlign/include/DDAlign/GlobalAlignmentCache.h @@ -14,6 +14,7 @@ #define DD4HEP_ALIGNMENT_GLOBALALIGNMENTCACHE_H // Framework include files +#include "DD4hep/ExtensionEntry.h" #include "DD4hep/GlobalAlignment.h" #include "DDAlign/GlobalAlignmentStack.h" @@ -40,6 +41,7 @@ namespace dd4hep { class GlobalAlignmentCache { friend class dd4hep::Detector; friend class GlobalAlignmentOperator; + friend class dd4hep::detail::DeleteExtension<GlobalAlignmentCache,GlobalAlignmentCache>; public: typedef GlobalAlignmentStack Stack; diff --git a/DDAlign/src/GlobalAlignmentCache.cpp b/DDAlign/src/GlobalAlignmentCache.cpp index bb8249bee..fd36e2101 100644 --- a/DDAlign/src/GlobalAlignmentCache.cpp +++ b/DDAlign/src/GlobalAlignmentCache.cpp @@ -75,8 +75,8 @@ GlobalAlignmentCache* GlobalAlignmentCache::install(Detector& description) { GlobalAlignmentCache* cache = description.extension<GlobalAlignmentCache>(false); if ( !cache ) { cache = new GlobalAlignmentCache(description,"world",true); - description.addUserExtension(detail::typeHash64<GlobalAlignmentCache>(), - new detail::SimpleExtension<GlobalAlignmentCache>(cache)); + ExtensionEntry* e = new detail::DeleteExtension<GlobalAlignmentCache,GlobalAlignmentCache>(cache); + description.addUserExtension(detail::typeHash64<GlobalAlignmentCache>(),e); } return cache; } diff --git a/DDCore/include/DD4hep/DetElement.h b/DDCore/include/DD4hep/DetElement.h index cf9b37740..4d2514df7 100644 --- a/DDCore/include/DD4hep/DetElement.h +++ b/DDCore/include/DD4hep/DetElement.h @@ -124,7 +124,8 @@ namespace dd4hep { /// Extend the sensitive detector element with an arbitrary structure accessible by the type template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) const { - return (IFACE*) this->addExtension(detail::typeHash64<IFACE>(),new detail::DeleteExtension<CONCRETE>(c)); + return (IFACE*) this->addExtension(detail::typeHash64<IFACE>(), + new detail::DeleteExtension<IFACE,CONCRETE>(c)); } /// Access extension element by the type @@ -198,22 +199,25 @@ namespace dd4hep { protected: - template <typename T> struct DetElementExtension : public ExtensionEntry { + template <typename Q, typename T> struct DetElementExtension : public ExtensionEntry { protected: - T* ptr; + T* ptr = 0; + mutable Q* iface = 0; //! public: DetElementExtension() = delete; - DetElementExtension(T* p) : ptr(p) {} + DetElementExtension(T* p) : ptr(p) { iface = dynamic_cast<Q*>(p); } DetElementExtension(const DetElementExtension& copy) = default; DetElementExtension& operator=(const DetElementExtension& copy) = default; virtual ~DetElementExtension() = default; // This one ensures we have the correct signatures - T* copy(DetElement de) const { return new T(*ptr,de); } - virtual void* object() const override { return ptr; } - virtual void* copy(void* det) const override { return copy(DetElement((Object*)det)); } + T* copy(DetElement de) const { return new T(*ptr,de); } virtual void destruct() const override { delete ptr; } + virtual void* object() const override + { return iface ? iface : (iface=dynamic_cast<Q*>(ptr)); } + virtual void* copy(void* det) const override + { return copy(DetElement((Object*)det)); } virtual ExtensionEntry* clone(void* det) const override - { return new DetElementExtension<T>((T*)this->copy(det)); } + { return new DetElementExtension<Q,T>((T*)this->copy(det)); } }; /// Internal call to extend the detector element with an arbitrary structure accessible by the type @@ -285,7 +289,8 @@ namespace dd4hep { /// Extend the detector element with an arbitrary structure accessible by the type template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) const { CallbackSequence::checkTypes(typeid(IFACE), typeid(CONCRETE), dynamic_cast<IFACE*>(c)); - return (IFACE*) this->addExtension(detail::typeHash64<IFACE>(),new DetElementExtension<CONCRETE>(c)); + return (IFACE*) this->addExtension(detail::typeHash64<IFACE>(), + new DetElementExtension<IFACE,CONCRETE>(c)); } /// Access extension element by the type template <typename IFACE> IFACE* extension() const { diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h index 6e5363047..9d5c1fadb 100644 --- a/DDCore/include/DD4hep/Detector.h +++ b/DDCore/include/DD4hep/Detector.h @@ -266,15 +266,18 @@ namespace dd4hep { /// Add an extension object to the detector element (low level member function) virtual void* addUserExtension(unsigned long long int key, ExtensionEntry* entry) = 0; - /// Remove an existing extension object from the Detector instance. If not destroyed, the instance is returned (low level member function) + + /// Remove an existing extension object from the Detector instance. + /** If not destroyed, the instance is returned (low level member function) */ virtual void* removeUserExtension(unsigned long long int key, bool destroy) = 0; + /// Access an existing extension object from the detector element (low level member function) virtual void* userExtension(unsigned long long int key, bool alert=true) const = 0; /// Extend the sensitive detector element with an arbitrary structure accessible by the type - template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) { + template <typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) { return (IFACE*) addUserExtension(detail::typeHash64<IFACE>(), - new detail::DeleteExtension<IFACE>(dynamic_cast<IFACE*>(c))); + new detail::DeleteExtension<IFACE,CONCRETE>(c)); } /// Remove an existing extension object from the Detector instance. If not destroyed, the instance is returned diff --git a/DDCore/include/DD4hep/ExtensionEntry.h b/DDCore/include/DD4hep/ExtensionEntry.h index c227c2af3..9542523bc 100644 --- a/DDCore/include/DD4hep/ExtensionEntry.h +++ b/DDCore/include/DD4hep/ExtensionEntry.h @@ -60,109 +60,128 @@ namespace dd4hep { namespace detail { /// Implementation class for the object extension mechanism. - /** This implementation class supports the object extension mechanism - * for dd4hep. + /** This implementation class supports the object extension mechanism + * for dd4hep. + * + * Note: + * The double-template implementation is necessary to support extensions + * using a virtual inheritance relationship between the interface and the + * concrete implementation of the extension object. * * \author M.Frank * \date 13.08.2013 * \ingroup DD4HEP */ - template <typename T> struct SimpleExtension : public ExtensionEntry { + template <typename Q,typename T> struct SimpleExtension : public ExtensionEntry { protected: - T* ptr; + T* ptr = 0; + mutable Q* iface = 0; //! public: /// Default constructor SimpleExtension() = delete; /// Initializing constructor - SimpleExtension(T* p) : ptr(p) {} + SimpleExtension(T* p) : ptr(p) { iface = dynamic_cast<Q*>(p); } /// Copy constructor SimpleExtension(const SimpleExtension& copy) = default; /// Default destructor virtual ~SimpleExtension() = default; /// Assignment operator SimpleExtension& operator=(const SimpleExtension& copy) = default; - /// Virtual object accessor - virtual void* object() const override { return ptr; } /// Virtual object copy operator virtual void* copy(void*) const override { invalidCall("copy"); return 0; } - /// Virtual object destructor - virtual void destruct() const override { invalidCall("destruct"); return; } + /// Virtual object destructor. Function may still be called without side-effects. + virtual void destruct() const override { } + /// Virtual object accessor + virtual void* object() const override + { return iface ? iface : (iface=dynamic_cast<Q*>(ptr)); } /// Virtual entry clone function virtual ExtensionEntry* clone(void*) const override { invalidCall("clone"); return 0; } }; - + /// Implementation class for the object extension mechanism. - /** This implementation class supports the object extension mechanism - * for dd4hep. It is ensured, that on the object destruction or - * on request the reference to the user object may be destructed. + /** This implementation class supports the object extension mechanism + * for dd4hep. It is ensured, that on the object destruction or + * on request the reference to the user object may be destructed. * - * Note: User object must be taken from the heap using "new". + * Note: User object must be taken from the heap using "new". + * Note: + * The double-template implementation is necessary to support extensions + * using a virtual inheritance relationship between the interface and the + * concrete implementation of the extension object. * * \author M.Frank * \date 13.08.2013 * \ingroup DD4HEP */ - template <typename T> struct DeleteExtension : public ExtensionEntry { + template <typename Q,typename T> struct DeleteExtension : public ExtensionEntry { protected: - T* ptr; + T* ptr = 0; + mutable Q* iface = 0; //! public: /// Default constructor DeleteExtension() = delete; /// Initializing constructor - DeleteExtension(T* p) : ptr(p) {} + DeleteExtension(T* p) : ptr(p) { iface = dynamic_cast<Q*>(p); } /// Copy constructor DeleteExtension(const DeleteExtension& copy) = default; /// Default destructor virtual ~DeleteExtension() = default; /// Assignment operator DeleteExtension& operator=(const DeleteExtension& copy) = default; - /// Virtual object accessor - virtual void* object() const override { return ptr; } /// Virtual object copy operator virtual void* copy(void*) const override { invalidCall("copy"); return 0; } /// Virtual object destructor virtual void destruct() const override { delete ptr; } + /// Virtual object accessor + virtual void* object() const override + { return iface ? iface : (iface=dynamic_cast<Q*>(ptr)); } /// Virtual entry clone function virtual ExtensionEntry* clone(void* arg) const override { return new DeleteExtension((T*)this->copy(arg)); } }; /// Implementation class for the object extension mechanism. - /** This implementation class supports the object extension mechanism - * for dd4hep. It is ensured, that on the object destruction or - * on request the reference to the user object may be destructed. + /** This implementation class supports the object extension mechanism + * for dd4hep. It is ensured, that on the object destruction or + * on request the reference to the user object may be destructed. * - * Note: User object must be taken from the heap using "new". + * Note: User object must be taken from the heap using "new". + * Note: + * The double-template implementation is necessary to support extensions + * using a virtual inheritance relationship between the interface and the + * concrete implementation of the extension object. * * \author M.Frank * \date 13.08.2013 * \ingroup DD4HEP */ - template <typename T> struct CopyDeleteExtension : public ExtensionEntry { + template <typename Q,typename T> struct CopyDeleteExtension : public ExtensionEntry { protected: - T* ptr; + T* ptr = 0; + mutable Q* iface = 0; //! public: /// Default constructor CopyDeleteExtension() = delete; /// Initializing constructor - CopyDeleteExtension(T* p) : ptr(p) {} + CopyDeleteExtension(T* p) : ptr(p) { iface = dynamic_cast<Q*>(p); } /// Copy constructor CopyDeleteExtension(const CopyDeleteExtension& copy) = default; /// Default destructor virtual ~CopyDeleteExtension() = default; /// Assignment operator CopyDeleteExtension& operator=(const CopyDeleteExtension& copy) = default; - /// Virtual object accessor - virtual void* object() const override { return ptr; } /// Virtual object copy operator virtual void* copy(void*) const override { return new T(*ptr); } /// Virtual object destructor virtual void destruct() const override { delete ptr; } + /// Virtual object accessor + virtual void* object() const override + { return iface ? iface : (iface=dynamic_cast<Q*>(ptr)); } /// Virtual entry clone function virtual ExtensionEntry* clone(void* arg) const override { return new CopyDeleteExtension((T*)this->copy(arg)); } }; } // End namespace detail - } // End namespace dd4hep +} // End namespace dd4hep #endif /* DD4HEP_DDCORE_EXTENSIONENTRY_H */ diff --git a/DDCore/src/ExtensionEntry.cpp b/DDCore/src/ExtensionEntry.cpp index 250203c29..f22876858 100644 --- a/DDCore/src/ExtensionEntry.cpp +++ b/DDCore/src/ExtensionEntry.cpp @@ -17,6 +17,6 @@ /// Callback on invalid call invokation void dd4hep::ExtensionEntry::invalidCall(const char* tag) const { - except("ExtensionEntry","Invalid call invokation from %s to method %s(...).", + except("ExtensionEntry","Invalid call invocation from %s to method %s(...).", typeName(typeid(*this)).c_str(), tag); } diff --git a/DDCore/src/ObjectExtensions.cpp b/DDCore/src/ObjectExtensions.cpp index bbb9212a2..dd288c2f5 100644 --- a/DDCore/src/ObjectExtensions.cpp +++ b/DDCore/src/ObjectExtensions.cpp @@ -95,7 +95,7 @@ void* ObjectExtensions::removeExtension(unsigned long long int key, bool destroy void* ObjectExtensions::extension(unsigned long long int key) const { const auto j = extensions.find(key); if (j != extensions.end()) { - return (*j).second; + return (*j).second->object(); } except("removeExtension","The object has no extension of type %016llX.",key); return 0; @@ -105,7 +105,7 @@ void* ObjectExtensions::extension(unsigned long long int key) const { void* ObjectExtensions::extension(unsigned long long int key, bool alert) const { const auto j = extensions.find(key); if (j != extensions.end()) { - return (*j).second; + return (*j).second->object(); } else if ( !alert ) return 0; diff --git a/DDG4/include/DDG4/Geant4Context.h b/DDG4/include/DDG4/Geant4Context.h index 030cbaba0..2500bc211 100644 --- a/DDG4/include/DDG4/Geant4Context.h +++ b/DDG4/include/DDG4/Geant4Context.h @@ -86,8 +86,8 @@ namespace dd4hep { /// Add user extension object. Ownership is transferred! template <typename T> T* addExtension(T* ptr, bool take_ownership=true) { ExtensionEntry* e = take_ownership - ? (ExtensionEntry*)new detail::DeleteExtension<T>(ptr) - : (ExtensionEntry*)new detail::SimpleExtension<T>(ptr); + ? (ExtensionEntry*)new detail::DeleteExtension<T,T>(ptr) + : (ExtensionEntry*)new detail::SimpleExtension<T,T>(ptr); return (T*)ObjectExtensions::addExtension(detail::typeHash64<T>(),e); } /// Access to type safe extension object. Exception is thrown if the object is invalid @@ -142,8 +142,8 @@ namespace dd4hep { /// Add user extension object. Ownership is transferred and object deleted at the end of the event. template <typename T> T* addExtension(T* ptr, bool take_ownership=true) { ExtensionEntry* e = take_ownership - ? (ExtensionEntry*)new detail::DeleteExtension<T>(ptr) - : (ExtensionEntry*)new detail::SimpleExtension<T>(ptr); + ? (ExtensionEntry*)new detail::DeleteExtension<T,T>(ptr) + : (ExtensionEntry*)new detail::SimpleExtension<T,T>(ptr); return (T*)ObjectExtensions::addExtension(detail::typeHash64<T>(),e); } /// Access to type safe extension object. Exception is thrown if the object is invalid -- GitLab