Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/GaudiKernel/ToolHandle.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 *                                                                                   *
0004 * This software is distributed under the terms of the Apache version 2 licence,     *
0005 * copied verbatim in the file "LICENSE".                                            *
0006 *                                                                                   *
0007 * In applying this licence, CERN does not waive the privileges and immunities       *
0008 * granted to it by virtue of its status as an Intergovernmental Organization        *
0009 * or submit itself to any jurisdiction.                                             *
0010 \***********************************************************************************/
0011 #ifndef GAUDIKERNEL_TOOLHANDLE_H
0012 #define GAUDIKERNEL_TOOLHANDLE_H
0013 
0014 // Includes
0015 #include <GaudiKernel/GaudiHandle.h>
0016 #include <GaudiKernel/IAlgTool.h>
0017 #include <GaudiKernel/IBinder.h>
0018 #include <GaudiKernel/INamedInterface.h>
0019 #include <GaudiKernel/IToolSvc.h>
0020 #include <GaudiKernel/ServiceHandle.h>
0021 #include <GaudiKernel/TaggedBool.h>
0022 
0023 #include <stdexcept>
0024 #include <string>
0025 #include <type_traits>
0026 #include <vector>
0027 
0028 // forward declarations
0029 class IInterface;
0030 class IToolSvc;
0031 
0032 namespace Gaudi {
0033   class Algorithm;
0034 }
0035 class AlgTool;
0036 class Service;
0037 
0038 using DisableTool = Gaudi::tagged_bool<class DisableTool_tag>;
0039 using EnableTool  = Gaudi::tagged_bool<class EnableTool_tag>;
0040 
0041 /** General info and helper functions for toolhandles and arrays */
0042 class ToolHandleInfo {
0043 
0044 protected:
0045   ToolHandleInfo( const IInterface* parent = nullptr, bool createIf = true )
0046       : m_parent( parent ), m_createIf( createIf ) {}
0047 
0048 public:
0049   virtual ~ToolHandleInfo() = default;
0050 
0051   bool isPublic() const noexcept { return !m_parent; }
0052 
0053   bool createIf() const noexcept { return m_createIf; }
0054 
0055   const IInterface* parent() const noexcept { return m_parent; }
0056 
0057   //
0058   // Some helper functions
0059   //
0060 
0061   static std::string toolComponentType( const IInterface* parent ) { return parent ? "PrivateTool" : "PublicTool"; }
0062 
0063   static std::string toolParentName( const IInterface* parent ) {
0064     auto* pNamed = ( parent ? dynamic_cast<const INamedInterface*>( parent ) : nullptr );
0065     return ( !parent ? "ToolSvc" : ( pNamed ? pNamed->name() : "" ) );
0066   }
0067 
0068 protected:
0069   const IInterface* m_parent = nullptr;
0070   bool              m_createIf{ true };
0071 };
0072 
0073 /** @class BaseToolHandle ToolHandle.h GaudiKernel/ToolHandle.h
0074 
0075     Non-templated base class for actual ToolHandle<T>.
0076     Defines the interface for the management of ToolHandles in the Algorithms and Tools
0077 
0078     @author Daniel Funke <daniel.funke@cern.ch>
0079 */
0080 class BaseToolHandle : public ToolHandleInfo {
0081 
0082 protected:
0083   BaseToolHandle( const IInterface* parent = nullptr, bool createIf = true ) : ToolHandleInfo( parent, createIf ) {}
0084 
0085   virtual StatusCode i_retrieve( IAlgTool*& ) const = 0;
0086 
0087 public:
0088   StatusCode retrieve( IAlgTool*& tool ) const { return i_retrieve( tool ); }
0089 
0090   virtual StatusCode retrieve() const           = 0;
0091   virtual StatusCode retrieve( DisableTool sd ) = 0;
0092   virtual StatusCode retrieve( EnableTool sd )  = 0;
0093 
0094   const IAlgTool* get() const { return getAsIAlgTool(); }
0095 
0096   IAlgTool* get() { return getAsIAlgTool(); }
0097 
0098   virtual std::string typeAndName() const = 0;
0099 
0100   /// Helper to check if the ToolHandle should be retrieved.
0101   bool isEnabled() const {
0102     // the handle is considered enabled if the type/name is valid and the
0103     // enabled flag was set to true, or it was already retrieved
0104     return ( m_enabled && !typeAndName().empty() ) || get();
0105   }
0106 
0107   void enable() { m_enabled = true; }
0108 
0109   void disable() { m_enabled = false; }
0110 
0111   bool setEnabled( bool flag ) { return std::exchange( m_enabled, flag ); }
0112 
0113 protected:
0114   virtual const IAlgTool* getAsIAlgTool() const = 0;
0115 
0116   virtual IAlgTool* getAsIAlgTool() = 0;
0117 
0118   bool m_enabled = true;
0119 };
0120 
0121 /** @class ToolHandle ToolHandle.h GaudiKernel/ToolHandle.h
0122 
0123     Handle to be used in lieu of naked pointers to tools. This allows
0124     better control through the framework of tool loading and usage.
0125     @paramater T is the AlgTool interface class (or concrete class) of
0126     the tool to use, and must derive from IAlgTool.
0127 
0128     @author Wim Lavrijsen <WLavrijsen@lbl.gov>
0129     @author Martin.Woudstra@cern.ch
0130 */
0131 template <class T>
0132 class ToolHandle : public BaseToolHandle, public GaudiHandle<T> {
0133 
0134   friend class Gaudi::Algorithm;
0135   friend class AlgTool;
0136   friend class Service;
0137 
0138   template <typename... Args, std::size_t... Is>
0139   ToolHandle( std::tuple<Args...>&& args, std::index_sequence<Is...> )
0140       : ToolHandle( std::get<Is>( std::move( args ) )... ) {}
0141 
0142 public:
0143   /** Constructor for a tool with default tool type and name.
0144       Can be called only if the type T is a concrete tool type (not an interface),
0145       and you want to use the default name. */
0146   ToolHandle( const IInterface* parent = nullptr, bool createIf = true )
0147       : BaseToolHandle( parent, createIf )
0148       , GaudiHandle<T>( "", toolComponentType( parent ), toolParentName( parent ) )
0149       , m_pToolSvc( "ToolSvc", GaudiHandleBase::parentName() ) {}
0150 
0151   /** Copy constructor from a non const T to const T tool handle */
0152   template <typename CT = T, typename NCT = std::remove_const_t<T>>
0153     requires( std::is_const_v<CT> && !std::is_same_v<CT, NCT> )
0154   ToolHandle( const ToolHandle<NCT>& other )
0155       : BaseToolHandle( other.parent(), other.createIf() )
0156       , GaudiHandle<CT>( other )
0157       , m_pToolSvc( "ToolSvc", GaudiHandleBase::parentName() ) {}
0158 
0159 public:
0160   //
0161   // Constructors etc.
0162   //
0163 
0164   /** Create a handle ('smart pointer') to a tool.
0165       The arguments are passed on to ToolSvc, and have the same meaning:
0166       @code
0167       StatusCode ToolSvc::retrieveTool ( const std::string& type            ,
0168                                          T*&                tool            ,
0169                                          const IInterface*  parent   = 0    ,
0170                                          bool               createIf = true )
0171       @endcode
0172       @param owner: class owning the ToolHandle
0173       @param toolType: "MyToolType/MyToolName"
0174                        "MyToolType" is short for "MyToolType/MyToolType"
0175                        'MyToolType' is the name of the class of the concrete tool
0176                        'MyToolName' is to distinguish several tool instances of the same class
0177       @param parent: the parent Algorithm,Tool or Service of which this tool is a member.
0178                      If non-zero, the the tool is a private tool of the parent, otherwise it is
0179                      a public (shared) tool.
0180       @param createIf: if true, create tool if not yet existing.
0181   */
0182 
0183 #if defined( TOOLHANDLE_DEPR_WARN )
0184 // warn about using deprecated explicit ToolHandle construction
0185 #  pragma message( "Untracked ToolHandle: Migrate explicit DataHandle constructor to declareTool Algorithm Property" )
0186 
0187   __attribute__( ( deprecated ) )
0188 
0189 #endif
0190   ToolHandle( const std::string& toolTypeAndName, const IInterface* parent = nullptr, bool createIf = true )
0191       : BaseToolHandle( parent, createIf )
0192       , GaudiHandle<T>( toolTypeAndName, toolComponentType( parent ), toolParentName( parent ) )
0193       , m_pToolSvc( "ToolSvc", GaudiHandleBase::parentName() ) {
0194   }
0195 
0196   /// Autodeclaring constructor with property propName, tool type/name and documentation.
0197   /// @note the use of requires is required to avoid ambiguities
0198   template <std::derived_from<IProperty> OWNER>
0199   ToolHandle( OWNER* owner, std::string propName, std::string toolType, std::string doc = "" ) : ToolHandle( owner ) {
0200     // convert name and type to a valid type/name string
0201     // - if type does not contain '/' use type/type
0202     // - otherwise type is already a type/name string
0203     if ( !toolType.empty() and toolType.find( '/' ) == std::string::npos ) { toolType += '/' + toolType; }
0204     owner->declareTool( *this, std::move( toolType ) ).ignore();
0205     auto p = owner->OWNER::PropertyHolderImpl::declareProperty( std::move( propName ), *this, std::move( doc ) );
0206     p->template setOwnerType<OWNER>();
0207   }
0208 
0209   template <typename... Args>
0210   ToolHandle( std::tuple<Args...>&& args ) : ToolHandle( std::move( args ), std::index_sequence_for<Args...>{} ) {}
0211 
0212 public:
0213   StatusCode initialize( const std::string& toolTypeAndName, const IInterface* parent = nullptr,
0214                          bool createIf = true ) {
0215 
0216     GaudiHandleBase::setTypeAndName( toolTypeAndName );
0217     GaudiHandleBase::setComponentType( toolComponentType( parent ) );
0218     GaudiHandleBase::setParentName( toolParentName( parent ) );
0219 
0220     m_parent   = parent;
0221     m_createIf = createIf;
0222 
0223     return m_pToolSvc.initialize( "ToolSvc", GaudiHandleBase::parentName() );
0224   }
0225 
0226   /** Retrieve the AlgTool. Release existing tool if needed.
0227       Function must be repeated here to avoid hiding the function retrieve( T*& ) */
0228   StatusCode retrieve() const override { // not really const, because it updates m_pObject
0229     return GaudiHandle<T>::retrieve();
0230   }
0231 
0232   StatusCode retrieve( DisableTool sd ) override {
0233     if ( isEnabled() && sd == DisableTool{ false } ) {
0234       return GaudiHandle<T>::retrieve();
0235     } else {
0236       disable();
0237       return StatusCode::SUCCESS;
0238     }
0239   }
0240 
0241   StatusCode retrieve( EnableTool sd ) override {
0242     if ( isEnabled() && sd == EnableTool{ true } ) {
0243       return GaudiHandle<T>::retrieve();
0244     } else {
0245       disable();
0246       return StatusCode::SUCCESS;
0247     }
0248   }
0249 
0250   /** Release the AlgTool.
0251       Function must be repeated here to avoid hiding the function release( T*& ) */
0252   StatusCode release() const { // not really const, because it updates m_pObject
0253     return GaudiHandle<T>::release();
0254   }
0255 
0256   /** Do the real retrieval of the AlgTool. */
0257   StatusCode retrieve( T*& algTool ) const override {
0258     IAlgTool* iface = nullptr;
0259     if ( i_retrieve( iface ).isFailure() ) { return StatusCode::FAILURE; }
0260 
0261     algTool = dynamic_cast<T*>( iface );
0262     if ( !algTool ) {
0263       throw GaudiException( "unable to dcast AlgTool " + typeAndName() + " to interface " +
0264                                 System::typeinfoName( typeid( T ) ),
0265                             typeAndName() + " retrieve", StatusCode::FAILURE );
0266     }
0267     return StatusCode::SUCCESS;
0268   }
0269 
0270   /** Do the real release of the AlgTool. */
0271   StatusCode release( T* algTool ) const override { return m_pToolSvc->releaseTool( ::details::nonConst( algTool ) ); }
0272 
0273   std::string typeAndName() const override { return GaudiHandleBase::typeAndName(); }
0274 
0275   std::add_const_t<T>* get() const { return GaudiHandle<T>::get(); }
0276 
0277   T* get() { return GaudiHandle<T>::get(); }
0278 
0279   friend std::ostream& operator<<( std::ostream& os, const ToolHandle<T>& handle ) {
0280     return os << static_cast<const GaudiHandleInfo&>( handle );
0281   }
0282 
0283 protected:
0284   const IAlgTool* getAsIAlgTool() const override {
0285     // const cast to support T being const
0286     return GaudiHandle<T>::get();
0287   }
0288 
0289   IAlgTool* getAsIAlgTool() override {
0290     // const cast to support T being const
0291     return ::details::nonConst( GaudiHandle<T>::get() );
0292   }
0293 
0294   StatusCode i_retrieve( IAlgTool*& algTool ) const override {
0295     return m_pToolSvc->retrieve( typeAndName(), IAlgTool::interfaceID(), algTool, ToolHandleInfo::parent(),
0296                                  ToolHandleInfo::createIf() );
0297   }
0298 
0299 private:
0300   //
0301   // Private data members
0302   //
0303   mutable ServiceHandle<IToolSvc> m_pToolSvc;
0304 };
0305 
0306 // explicit specialization for IBinder<IFace>
0307 template <typename IFace>
0308 class ToolHandle<Gaudi::Interface::Bind::IBinder<IFace>> : public ToolHandle<IAlgTool> {
0309 
0310   void* m_ptr                                                                        = nullptr;
0311   Gaudi::Interface::Bind::Box<IFace> ( *m_bind )( void const*, const EventContext& ) = nullptr;
0312 
0313 public:
0314   using ToolHandle<IAlgTool>::ToolHandle;
0315   using ToolHandle<IAlgTool>::retrieve;
0316   StatusCode retrieve() const override {
0317     // FIXME: why is `retrieve` const????
0318     auto self = const_cast<ToolHandle<Gaudi::Interface::Bind::IBinder<IFace>>*>( this );
0319 
0320     return ToolHandle<IAlgTool>::retrieve().andThen( [&] {
0321       const IAlgTool* tool = get();
0322       assert( tool != nullptr ); // retrieve was succesfull, so get() better return something valid!
0323       return const_cast<IAlgTool*>( tool )
0324           ->queryInterface( IFace::interfaceID(), &( self->m_ptr ) )
0325           .andThen( [&] {
0326             // TODO: what happens to the refCount?
0327             self->m_bind = []( const void* ptr, const EventContext& ) {
0328               return Gaudi::Interface::Bind::Box<IFace>( static_cast<IFace const*>( ptr ) );
0329             };
0330           } )
0331           .orElse( [&]() {
0332             return const_cast<IAlgTool*>( tool )
0333                 ->queryInterface( Gaudi::Interface::Bind::IBinder<IFace>::interfaceID(), &( self->m_ptr ) )
0334                 .andThen( [&] {
0335                   // TODO: what happens to the refCount?
0336                   self->m_bind = []( const void* ptr, const EventContext& ctx ) {
0337                     return static_cast<Gaudi::Interface::Bind::IBinder<IFace> const*>( ptr )->bind( ctx );
0338                   };
0339                 } );
0340           } );
0341     } );
0342   }
0343 
0344   auto bind( const EventContext& ctx ) const {
0345     if ( !m_bind || !m_ptr ) {
0346       throw GaudiException{ "request bind on toolhandle which was not (successfully) 'retrieved'", __PRETTY_FUNCTION__,
0347                             StatusCode::FAILURE };
0348     }
0349     return ( *m_bind )( m_ptr, ctx );
0350   }
0351 };
0352 
0353 /** Helper class to construct ToolHandle instances for public tools via the
0354  *  auto registering constructor.
0355  */
0356 template <class T>
0357 class PublicToolHandle : public ToolHandle<T> {
0358 public:
0359   PublicToolHandle( bool createIf = true ) : ToolHandle<T>( nullptr, createIf ) {}
0360   PublicToolHandle( const char* toolTypeAndName, bool createIf = true )
0361       : PublicToolHandle{ std::string{ toolTypeAndName }, createIf } {}
0362   PublicToolHandle( const std::string& toolTypeAndName, bool createIf = true )
0363       : ToolHandle<T>( toolTypeAndName, nullptr, createIf ) {}
0364 
0365   /// Copy constructor from a non const T to const T tool handle
0366   template <typename CT = T, typename NCT = std::remove_const_t<T>>
0367     requires( std::is_const_v<CT> && !std::is_same_v<CT, NCT> )
0368   PublicToolHandle( const PublicToolHandle<NCT>& other )
0369       : ToolHandle<T>( static_cast<const ToolHandle<NCT>&>( other ) ) {}
0370 
0371   /// Autodeclaring constructor with property propName, tool type/name and documentation.
0372   /// @note the use of requires is required to avoid ambiguities
0373   template <std::derived_from<IProperty> OWNER>
0374   inline PublicToolHandle( OWNER* owner, std::string propName, std::string toolType, std::string doc = "" )
0375       : PublicToolHandle() {
0376     // convert name and type to a valid type/name string
0377     // - if type does not contain '/' use type/type
0378     // - otherwise type is already a type/name string
0379     if ( !toolType.empty() and toolType.find( '/' ) == std::string::npos ) { toolType += '/' + toolType; }
0380     owner->declareTool( *this, std::move( toolType ) ).ignore();
0381     auto p = owner->OWNER::PropertyHolderImpl::declareProperty( std::move( propName ), *this, std::move( doc ) );
0382     p->template setOwnerType<OWNER>();
0383   }
0384 };
0385 
0386 //-------------------------------------------------------------------------//
0387 
0388 /** @class ToolHandleArray ToolHandle.h GaudiKernel/ToolHandle.h
0389 
0390     Array of Handles to be used in lieu of vector of naked pointers to tools.
0391     This allows better control through the framework of tool loading and usage.
0392     @parameter T is the AlgTool interface class (or concrete class) of
0393     the tool to use, and must derive from IAlgTool.
0394 
0395     @author Martin.Woudstra@cern.ch
0396 */
0397 
0398 template <class T>
0399 class ToolHandleArray : public ToolHandleInfo, public GaudiHandleArray<ToolHandle<T>> {
0400 public:
0401   //
0402   // Constructors
0403   //
0404   /** Generic constructor. Probably not very useful...
0405       @param typesAndNamesList : a vector of strings with the concrete "type/name" strings
0406       for the list of tools
0407       @param parent   : passed on to ToolHandle, so has the same meaning as for ToolHandle
0408       @param createIf : passed on to ToolHandle, so has the same meaning as for ToolHandle
0409   */
0410   ToolHandleArray( const std::vector<std::string>& myTypesAndNames, const IInterface* parent = nullptr,
0411                    bool createIf = true )
0412       : ToolHandleInfo( parent, createIf )
0413       , GaudiHandleArray<ToolHandle<T>>( myTypesAndNames, ToolHandleInfo::toolComponentType( parent ),
0414                                          ToolHandleInfo::toolParentName( parent ) ) {}
0415 
0416   /** Constructor which creates and empty list.
0417       @param parent   : passed on to ToolHandle, so has the same meaning as for ToolHandle
0418       @param createIf : passed on to ToolHandle, so has the same meaning as for ToolHandle
0419   */
0420   ToolHandleArray( const IInterface* parent = nullptr, bool createIf = true )
0421       : ToolHandleInfo( parent, createIf )
0422       , GaudiHandleArray<ToolHandle<T>>( ToolHandleInfo::toolComponentType( parent ),
0423                                          ToolHandleInfo::toolParentName( parent ) ) {}
0424 
0425   /** Add a handle to the array with given tool type and name.
0426       This function overrides the one in GaudiHandleArray<T>, as this is a special case.
0427       The private/public choice and createIf is determined by what was given
0428       in the constructor of the ToolHandleArray. */
0429   bool push_back( const std::string& toolTypeAndName ) override {
0430     ToolHandle<T> handle( toolTypeAndName, ToolHandleInfo::parent(), ToolHandleInfo::createIf() );
0431     GaudiHandleArray<ToolHandle<T>>::push_back( handle );
0432     return true;
0433   }
0434 
0435   /** Ensure that for added handles the parent and creatIf are taken from this array. */
0436   bool push_back( const ToolHandle<T>& myHandle ) override { return push_back( myHandle.typeAndName() ); }
0437 
0438   /// Autodeclaring constructor with property name, tool type/name and documentation.
0439   /// @note the use of requires is required to avoid ambiguities
0440   template <std::derived_from<IProperty> OWNER>
0441   inline ToolHandleArray( OWNER* owner, std::string name, const std::vector<std::string>& typesAndNames = {},
0442                           std::string doc = "" )
0443       : ToolHandleArray( owner ) {
0444     owner->addToolsArray( *this );
0445     this->setTypesAndNames( typesAndNames );
0446     auto p = owner->OWNER::PropertyHolderImpl::declareProperty( std::move( name ), *this, std::move( doc ) );
0447     p->template setOwnerType<OWNER>();
0448   }
0449 
0450   friend std::ostream& operator<<( std::ostream& os, const ToolHandleArray<T>& handle ) {
0451     return os << static_cast<const GaudiHandleInfo&>( handle );
0452   }
0453 };
0454 
0455 /** Helper class to construct ToolHandle instances for public tools via the
0456  *  auto registering constructor.
0457  */
0458 template <class T>
0459 class PublicToolHandleArray : public ToolHandleArray<T> {
0460 public:
0461   PublicToolHandleArray( bool createIf = true ) : ToolHandleArray<T>( nullptr, createIf ) {}
0462   PublicToolHandleArray( const std::vector<std::string>& typesAndNames, bool createIf = true )
0463       : ToolHandleArray<T>( typesAndNames, nullptr, createIf ) {}
0464 
0465   /// Autodeclaring constructor with property name, tool type/name and documentation.
0466   /// @note the use of requires is required to avoid ambiguities
0467   template <std::derived_from<IProperty> OWNER>
0468   PublicToolHandleArray( OWNER* owner, std::string name, const std::vector<std::string>& typesAndNames = {},
0469                          std::string doc = "" )
0470       : PublicToolHandleArray() {
0471     owner->addToolsArray( *this );
0472     this->setTypesAndNames( typesAndNames );
0473     auto p = owner->OWNER::PropertyHolderImpl::declareProperty( std::move( name ), *this, std::move( doc ) );
0474     p->template setOwnerType<OWNER>();
0475   }
0476 };
0477 
0478 #endif // ! GAUDIKERNEL_TOOLHANDLE_H