Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:29

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