Back to home page

EIC code displayed by LXR

 
 

    


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

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