Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:59

0001 #ifndef GAUDIPLUGINSERVICE_GAUDI_PLUGINSERVICEV2_H
0002 #define GAUDIPLUGINSERVICE_GAUDI_PLUGINSERVICEV2_H
0003 /*****************************************************************************\
0004 * (c) Copyright 2013 CERN                                                     *
0005 *                                                                             *
0006 * This software is distributed under the terms of the GNU General Public      *
0007 * Licence version 3 (GPL Version 3), copied verbatim in the file "LICENCE".   *
0008 *                                                                             *
0009 * In applying this licence, CERN does not waive the privileges and immunities *
0010 * granted to it by virtue of its status as an Intergovernmental Organization  *
0011 * or submit itself to any jurisdiction.                                       *
0012 \*****************************************************************************/
0013 
0014 /// @author Marco Clemencic <marco.clemencic@cern.ch>
0015 /// See @ref GaudiPluginService-readme
0016 
0017 #include <Gaudi/Details/PluginServiceDetailsV2.h>
0018 #include <functional>
0019 #include <memory>
0020 #include <string>
0021 #include <type_traits>
0022 #include <typeinfo>
0023 #include <utility>
0024 
0025 namespace Gaudi {
0026   /// See @ref GaudiPluginService-readme
0027   namespace PluginService {
0028     GAUDI_PLUGIN_SERVICE_V2_INLINE namespace v2 {
0029       /// \cond FWD_DECL
0030       template <typename>
0031       struct Factory;
0032       /// \endcond
0033 
0034       /// Class wrapping the signature for a factory with any number of arguments.
0035       template <typename R, typename... Args>
0036       struct Factory<R( Args... )> {
0037         using Traits          = Details::Traits<R( Args... )>;
0038         using ReturnType      = typename Traits::ReturnType;
0039         using FactoryType     = typename Traits::FactoryType;
0040         using ReturnValueType = R;
0041 
0042         /// Function to call to create an instance of type identified by `id` and that uses this factory signature.
0043         template <typename T>
0044         static ReturnType create( const T& id, Args... args ) {
0045           try {
0046             return Details::Registry::instance().get<FactoryType>( Details::stringify_id( id ) )(
0047                 std::forward<Args>( args )... );
0048           } catch ( std::bad_any_cast& ) {
0049             Details::reportBadAnyCast( typeid( FactoryType ), Details::stringify_id( id ) );
0050             return nullptr;
0051           }
0052         }
0053       };
0054 
0055       /// Helper to declare the factory implementation for a user defined type `T`.
0056       ///
0057       /// The basic use is:
0058       /// ```cpp
0059       /// namespace {
0060       ///   Gaudi::PluginService::DeclareFactory<MyComponent> __some_random_name;
0061       /// }
0062       /// ```
0063       /// which is the equivalent of `DECLARE_COMPONENT( MyComponent )`.
0064       ///
0065       /// It's possible to specify a custom factory type (instead of the default type alias `MyComponent::Factory`):
0066       /// ```cpp
0067       /// namespace {
0068       ///   using namespace Gaudi::PluginService;
0069       ///   DeclareFactory<MyComponent, Factory<MyBase*( int, int )>> __some_random_name;
0070       /// }
0071       /// ```
0072       ///
0073       /// We can pass arguments to the constructor to use a custom factory function, or a special _id_, or properties:
0074       /// ```cpp
0075       /// namespace {
0076       ///   using namespace Gaudi::PluginService;
0077       ///   DeclareFactory<MyComponent> __some_random_name( "special-id",
0078       ///                                                   []() -> MyComponent::Factory::ReturnType {
0079       ///                                                     return std::make_unique<MyComponent>( "special-id" );
0080       ///                                                   },
0081       ///                                                   {{"MyProperty", "special"}} );
0082       /// }
0083       /// ```
0084       template <typename T, typename F = typename T::Factory>
0085       struct DeclareFactory {
0086         using DefaultFactory = Details::DefaultFactory<T, F>;
0087 
0088         DeclareFactory( typename F::FactoryType f = DefaultFactory{}, Details::Registry::Properties props = {} )
0089             : DeclareFactory( Details::demangle<T>(), std::move( f ), std::move( props ) ) {}
0090 
0091         DeclareFactory( const std::string& id, typename F::FactoryType f = DefaultFactory{},
0092                         Details::Registry::Properties props = {} ) {
0093           using Details::Registry;
0094 
0095           if ( props.find( "ClassName" ) == end( props ) ) props.emplace( "ClassName", Details::demangle<T>() );
0096 
0097           Registry::instance().add( id, {libraryName(), std::move( f ), std::move( props )} );
0098         }
0099 
0100         DeclareFactory( Details::Registry::Properties props )
0101             : DeclareFactory( DefaultFactory{}, std::move( props ) ) {}
0102 
0103       private:
0104         /// Helper to record the name of the library that declare the factory.
0105         static std::string libraryName() { return Details::getDSONameFor( reinterpret_cast<void*>( libraryName ) ); }
0106       };
0107     }
0108   } // namespace PluginService
0109 } // namespace Gaudi
0110 
0111 #define _PS_V2_DECLARE_COMPONENT( type )                                                                               \
0112   namespace {                                                                                                          \
0113     ::Gaudi::PluginService::v2::DeclareFactory<type> _PS_V2_INTERNAL_FACTORY_REGISTER_CNAME{};                         \
0114   }
0115 
0116 #define _PS_V2_DECLARE_COMPONENT_WITH_ID( type, id )                                                                   \
0117   namespace {                                                                                                          \
0118     ::Gaudi::PluginService::v2::DeclareFactory<type> _PS_V2_INTERNAL_FACTORY_REGISTER_CNAME{                           \
0119         ::Gaudi::PluginService::v2::Details::stringify_id( id )};                                                      \
0120   }
0121 
0122 #define _PS_V2_DECLARE_FACTORY( type, factory )                                                                        \
0123   namespace {                                                                                                          \
0124     ::Gaudi::PluginService::v2::DeclareFactory<type, factory> _PS_V2_INTERNAL_FACTORY_REGISTER_CNAME{};                \
0125   }
0126 
0127 #define _PS_V2_DECLARE_FACTORY_WITH_ID( type, id, factory )                                                            \
0128   namespace {                                                                                                          \
0129     ::Gaudi::PluginService::v2::DeclareFactory<type, factory> _PS_V2_INTERNAL_FACTORY_REGISTER_CNAME{                  \
0130         ::Gaudi::PluginService::v2::Details::stringify_id( id )};                                                      \
0131   }
0132 
0133 #if GAUDI_PLUGIN_SERVICE_USE_V2
0134 #  define DECLARE_COMPONENT( type ) _PS_V2_DECLARE_COMPONENT( type )
0135 #  define DECLARE_COMPONENT_WITH_ID( type, id ) _PS_V2_DECLARE_COMPONENT_WITH_ID( type, id )
0136 #  define DECLARE_FACTORY( type, factory ) _PS_V2_DECLARE_FACTORY( type, factory )
0137 #  define DECLARE_FACTORY_WITH_ID( type, id, factory ) _PS_V2_DECLARE_FACTORY_WITH_ID( type, id, factory )
0138 #endif
0139 
0140 #endif // GAUDIPLUGINSERVICE_GAUDI_PLUGINSERVICEV2_H