Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-04 07:51:06

0001 #ifndef GAUDIPLUGINSERVICE_GAUDI_DETAILS_PLUGINSERVICEDETAILSV2_H
0002 #define GAUDIPLUGINSERVICE_GAUDI_DETAILS_PLUGINSERVICEDETAILSV2_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 
0016 #include "Gaudi/Details/PluginServiceCommon.h"
0017 
0018 #include <any>
0019 
0020 #include <functional>
0021 #include <map>
0022 #include <memory>
0023 #include <mutex>
0024 #include <set>
0025 #include <sstream>
0026 #include <string>
0027 #include <typeinfo>
0028 #include <utility>
0029 
0030 namespace Gaudi {
0031   namespace PluginService {
0032     GAUDI_PLUGIN_SERVICE_V2_INLINE namespace v2 {
0033       /// \cond FWD_DECL
0034       template <typename>
0035       struct Factory;
0036       /// \cond
0037 
0038       /// Implementation details of Gaudi::PluginService
0039       namespace Details {
0040         template <typename>
0041         struct Traits;
0042 
0043         template <typename R, typename... Args>
0044         struct Traits<R( Args... )> {
0045           using ReturnType  = std::unique_ptr<std::remove_pointer_t<R>>;
0046           using FactoryType = std::function<ReturnType( Args... )>;
0047         };
0048 
0049         /// Return a canonical name for type_info object (implementation borrowed
0050         /// from GaudiKernel/System.h).
0051         GAUDIPS_API
0052         std::string demangle( const std::type_info& id );
0053 
0054         /// Return a canonical name for the template argument.
0055         template <typename T>
0056         inline std::string demangle() {
0057           return demangle( typeid( T ) );
0058         }
0059 
0060         /// Convert a generic `id` to `std::string` via `std::ostream::operator<<`.
0061         template <typename ID>
0062         inline std::string stringify_id( const ID& id ) {
0063           std::ostringstream o;
0064           o << id;
0065           return o.str();
0066         }
0067         /// Specialized no-op conversion from `std::string` to `std::string`.
0068         template <>
0069         inline std::string stringify_id<std::string>( const std::string& id ) {
0070           return id;
0071         }
0072 
0073         /// Helper to print debug output in case of mismatched FactoryType.
0074         void reportBadAnyCast( const std::type_info& factory_type, const std::string& id );
0075 
0076         /// Simple logging class, just to provide a default implementation.
0077         class GAUDIPS_API Logger {
0078         public:
0079           enum Level { Debug = 0, Info = 1, Warning = 2, Error = 3 };
0080           Logger( Level level = Warning ) : m_level( level ) {}
0081           virtual ~Logger() {}
0082           inline Level level() const { return m_level; }
0083           inline void  setLevel( Level level ) { m_level = level; }
0084           inline void  info( const std::string& msg ) { report( Info, msg ); }
0085           inline void  debug( const std::string& msg ) { report( Debug, msg ); }
0086           inline void  warning( const std::string& msg ) { report( Warning, msg ); }
0087           inline void  error( const std::string& msg ) { report( Error, msg ); }
0088 
0089         private:
0090           virtual void report( Level lvl, const std::string& msg );
0091           Level        m_level;
0092         };
0093 
0094         /// Return the current logger instance.
0095         GAUDIPS_API Logger& logger();
0096         /// Set the logger instance to use.
0097         /// It must be a new instance and the ownership is passed to the function.
0098         GAUDIPS_API void setLogger( Logger* logger );
0099 
0100         /// In-memory database of the loaded factories.
0101         class GAUDIPS_API Registry {
0102         public:
0103           using KeyType = std::string;
0104 
0105           /// Type used for the properties implementation.
0106           using Properties = std::map<KeyType, std::string>;
0107 
0108           struct FactoryInfo {
0109             std::string library;
0110             std::any    factory{};
0111             Properties  properties{};
0112 
0113             inline bool is_set() const { return factory.has_value(); }
0114             Properties::mapped_type getprop( const Properties::key_type& name ) const;
0115           };
0116 
0117           /// Type used for the database implementation.
0118           using FactoryMap = std::map<KeyType, FactoryInfo>;
0119 
0120           /// Get the factory function for a given `id` from the registry.
0121           template <typename F>
0122           F get( const KeyType& id ) {
0123             const FactoryInfo& info = Registry::instance().getInfo( id, true );
0124 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
0125             if ( !info.getprop( "ReflexName" ).empty() ) {
0126               const std::string real_name = info.getprop( "ClassName" );
0127               logger().warning( "requesting factory via old name '" + id + "' use '" +
0128                                 ( real_name.empty() ? "<undefined>" : real_name ) + "' instead" );
0129             }
0130 #endif
0131             return std::any_cast<F>( info.factory );
0132           }
0133 
0134           /// Retrieve the singleton instance of Registry.
0135           static Registry& instance();
0136 
0137           /// Add factory info to the registry (used internally by DeclareFactory).
0138           FactoryInfo& add( const KeyType& id, FactoryInfo info );
0139 
0140           /// Retrieve the FactoryInfo object for an `id`.
0141           const FactoryInfo& getInfo( const KeyType& id, const bool load = false ) const;
0142 
0143           /// Add a property to an already existing FactoryInfo object (via its `id`).
0144           Registry& addProperty( const KeyType& id, const KeyType& k, const std::string& v );
0145 
0146           /// Return a list of all the known and loaded factories
0147           std::set<KeyType> loadedFactoryNames() const;
0148 
0149           /// Return the known factories (loading the list if not yet done).
0150           ///
0151           /// At the first call, the internal database of known factories is
0152           /// filled with the name of the libraries containing them, using the
0153           /// ".components" files in the `LD_LIBRARY_PATH`.
0154           const FactoryMap& factories() const;
0155 
0156         private:
0157           /// Private constructor for the singleton pattern.
0158           Registry();
0159 
0160           /// Private copy constructor for the singleton pattern.
0161           Registry( const Registry& ) = delete;
0162 
0163           /// Return the known factories (loading the list if not yet done).
0164           FactoryMap& factories();
0165 
0166           /// Initialize the registry loading the list of factories from the
0167           /// .component files in the library search path.
0168           void initialize();
0169 
0170           /// Flag recording if the registry has been initialized or not.
0171           mutable std::once_flag m_initialized;
0172 
0173           /// Internal storage for factories.
0174           FactoryMap m_factories;
0175 
0176           /// Mutex used to control concurrent access to the internal data.
0177           mutable std::recursive_mutex m_mutex;
0178         };
0179 
0180         /// Class providing default factory functions.
0181         ///
0182         /// The template argument T is the class to be created, while the methods
0183         /// template argument S is the specific factory signature.
0184         template <typename, typename>
0185         struct DefaultFactory;
0186         template <typename T, typename R, typename... Args>
0187         struct DefaultFactory<T, Factory<R( Args... )>> {
0188           inline typename Factory<R( Args... )>::ReturnType operator()( Args... args ) {
0189             return std::make_unique<T>( std::move( args )... );
0190           }
0191         };
0192 
0193         /// Helper to get the name of the library containing a given pointer to function.
0194         ///
0195         /// Implementation borrowed from `DsoUtils.h` (genconf).
0196         std::string getDSONameFor( void* fptr );
0197       } // namespace Details
0198 
0199       /// Backward compatibility with Reflex.
0200       GAUDIPS_API void SetDebug( int debugLevel );
0201       /// Backward compatibility with Reflex.
0202       GAUDIPS_API int Debug();
0203     }
0204   } // namespace PluginService
0205 } // namespace Gaudi
0206 
0207 #define _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME_TOKEN( serial ) _register_##serial
0208 #define _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME( serial )                                                          \
0209   _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME_TOKEN( serial )
0210 #define _PS_V2_INTERNAL_FACTORY_REGISTER_CNAME _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME( __LINE__ )
0211 
0212 #endif // GAUDIPLUGINSERVICE_GAUDI_DETAILS_PLUGINSERVICEDETAILSV2_H