Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /***********************************************************************************\
0002 * (c) Copyright 2013-2019 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_V1_H_
0012 #define _GAUDI_PLUGIN_SERVICE_DETAILS_V1_H_
0013 
0014 /// @author Marco Clemencic <marco.clemencic@cern.ch>
0015 
0016 #include "Gaudi/Details/PluginServiceCommon.h"
0017 
0018 #include <map>
0019 #include <set>
0020 #include <sstream>
0021 #include <string>
0022 #include <typeinfo>
0023 #include <utility>
0024 
0025 #include <mutex>
0026 
0027 namespace Gaudi {
0028   namespace PluginService {
0029     GAUDI_PLUGIN_SERVICE_V1_INLINE namespace v1 {
0030       namespace Details {
0031         /// Class providing default factory functions.
0032         ///
0033         /// The template argument T is the class to be created, while the methods
0034         /// template argument S is the specific factory signature.
0035         template <class T>
0036         class Factory {
0037         public:
0038           template <typename S, typename... Args>
0039           static typename S::ReturnType create( Args&&... args ) {
0040             return new T( std::forward<Args>( args )... );
0041           }
0042         };
0043 
0044         /// Function used to load a specific factory function.
0045         /// @return the pointer to the factory function.
0046         GAUDIPS_API
0047         void* getCreator( const std::string& id, const std::string& type );
0048 
0049         /// Convoluted implementation of getCreator with an embedded
0050         /// reinterpret_cast, used to avoid the warning
0051         /// <pre>
0052         /// warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object
0053         /// </pre>
0054         /// It is an ugly trick but works.<br/>
0055         /// See:
0056         /// <ul>
0057         ///  <li>http://www.trilithium.com/johan/2004/12/problem-with-dlsym/</li>
0058         ///  <li>http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#573</li>
0059         ///  <li>http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#195</li>
0060         /// </ul>
0061         template <typename F>
0062         inline F getCreator( const std::string& id ) {
0063           union {
0064             void* src;
0065             F     dst;
0066           } p2p;
0067           p2p.src = getCreator( id, typeid( F ).name() );
0068           return p2p.dst;
0069         }
0070 
0071         /// Return a canonical name for type_info object (implementation borrowed
0072         ///  from GaudiKernel/System).
0073         GAUDIPS_API
0074         std::string demangle( const std::type_info& id );
0075 
0076         /// Return a canonical name for the template argument.
0077         template <typename T>
0078         inline std::string demangle() {
0079           return demangle( typeid( T ) );
0080         }
0081 
0082         /// In-memory database of the loaded factories.
0083         class GAUDIPS_API Registry {
0084         public:
0085           typedef std::string KeyType;
0086 
0087           /// Type used for the properties implementation.
0088           typedef std::map<KeyType, std::string> Properties;
0089 
0090           struct FactoryInfo {
0091             FactoryInfo( std::string lib, void* p = nullptr, std::string t = "", std::string rt = "",
0092                          std::string cn = "", Properties props = Properties() )
0093                 : library( std::move( lib ) )
0094                 , ptr( p )
0095                 , type( std::move( t ) )
0096                 , rtype( std::move( rt ) )
0097                 , className( std::move( cn ) )
0098                 , properties( std::move( props ) ) {}
0099 
0100             std::string library;
0101             void*       ptr;
0102             std::string type;
0103             std::string rtype;
0104             std::string className;
0105             Properties  properties;
0106 
0107             FactoryInfo& addProperty( const KeyType& k, std::string v ) {
0108               properties[k] = std::move( v );
0109               return *this;
0110             }
0111           };
0112 
0113           /// Type used for the database implementation.
0114           typedef std::map<KeyType, FactoryInfo> FactoryMap;
0115 
0116           /// Retrieve the singleton instance of Registry.
0117           static Registry& instance();
0118 
0119           /// Add a factory to the database.
0120           template <typename F, typename T, typename I>
0121           inline FactoryInfo& add( const I& id, typename F::FuncType ptr ) {
0122             union {
0123               typename F::FuncType src;
0124               void*                dst;
0125             } p2p;
0126             p2p.src = ptr;
0127             std::ostringstream o;
0128             o << id;
0129             return add( o.str(), p2p.dst, typeid( typename F::FuncType ).name(),
0130                         typeid( typename F::ReturnType ).name(), demangle<T>() );
0131           }
0132 
0133           /// Retrieve the factory for the given id.
0134           void* get( const std::string& id, const std::string& type ) const;
0135 
0136           /// Retrieve the FactoryInfo object for an id.
0137           const FactoryInfo& getInfo( const std::string& id ) const;
0138 
0139           /// Add a property to an already existing FactoryInfo object (via its id.)
0140           Registry& addProperty( const std::string& id, const std::string& k, const std::string& v );
0141 
0142           /// Return a list of all the known and loaded factories
0143           std::set<KeyType> loadedFactoryNames() const;
0144 
0145           /// Return the known factories (loading the list if not yet done).
0146           inline const FactoryMap& factories() const {
0147             if ( !m_initialized ) const_cast<Registry*>( this )->initialize();
0148             return m_factories;
0149           }
0150 
0151         private:
0152           /// Private constructor for the singleton pattern.
0153           /// At construction time, the internal database of known factories is
0154           /// filled with the name of the libraries containing them, using the
0155           /// ".components" files in the LD_LIBRARY_PATH.
0156           Registry();
0157 
0158           /// Private copy constructor for the singleton pattern.
0159           Registry( const Registry& ) : m_initialized( false ) {}
0160 
0161           /// Add a factory to the database.
0162           FactoryInfo& add( const std::string& id, void* factory, const std::string& type, const std::string& rtype,
0163                             const std::string& className, const Properties& props = Properties() );
0164 
0165           /// Return the known factories (loading the list if not yet done).
0166           inline FactoryMap& factories() {
0167             if ( !m_initialized ) initialize();
0168             return m_factories;
0169           }
0170 
0171           /// Initialize the registry loading the list of factories from the
0172           /// .component files in the library search path.
0173           void initialize();
0174 
0175           /// Flag recording if the registry has been initialized or not.
0176           bool m_initialized;
0177 
0178           /// Internal storage for factories.
0179           FactoryMap m_factories;
0180 
0181           /// Mutex used to control concurrent access to the internal data.
0182           mutable std::recursive_mutex m_mutex;
0183         };
0184 
0185         /// Simple logging class, just to provide a default implementation.
0186         class GAUDIPS_API Logger {
0187         public:
0188           enum Level { Debug = 0, Info = 1, Warning = 2, Error = 3 };
0189           Logger( Level level = Warning ) : m_level( level ) {}
0190           virtual ~Logger() {}
0191           inline Level level() const { return m_level; }
0192           inline void  setLevel( Level level ) { m_level = level; }
0193           inline void  info( const std::string& msg ) { report( Info, msg ); }
0194           inline void  debug( const std::string& msg ) { report( Debug, msg ); }
0195           inline void  warning( const std::string& msg ) { report( Warning, msg ); }
0196           inline void  error( const std::string& msg ) { report( Error, msg ); }
0197 
0198         private:
0199           virtual void report( Level lvl, const std::string& msg );
0200           Level        m_level;
0201         };
0202 
0203         /// Return the current logger instance.
0204         GAUDIPS_API Logger& logger();
0205         /// Set the logger instance to use.
0206         /// It must be a new instance and the ownership is passed to the function.
0207         GAUDIPS_API void setLogger( Logger* logger );
0208       } // namespace Details
0209 
0210       /// Backward compatibility with Reflex.
0211       GAUDIPS_API void SetDebug( int debugLevel );
0212       /// Backward compatibility with Reflex.
0213       GAUDIPS_API int Debug();
0214     }
0215   } // namespace PluginService
0216 } // namespace Gaudi
0217 
0218 #define _PS_V1_INTERNAL_FACTORY_REGISTER_CNAME( name, serial ) _register_##_##serial
0219 
0220 #define _PS_V1_INTERNAL_DECLARE_FACTORY_WITH_CREATOR( type, typecreator, id, factory, serial )                         \
0221   namespace {                                                                                                          \
0222     class _PS_V1_INTERNAL_FACTORY_REGISTER_CNAME( type, serial ) {                                                     \
0223     public:                                                                                                            \
0224       typedef factory      s_t;                                                                                        \
0225       typedef typecreator  f_t;                                                                                        \
0226       static s_t::FuncType creator() { return &f_t::create<s_t>; }                                                     \
0227       _PS_V1_INTERNAL_FACTORY_REGISTER_CNAME( type, serial )() {                                                       \
0228         using ::Gaudi::PluginService::v1::Details::Registry;                                                           \
0229         Registry::instance().add<s_t, type>( id, creator() );                                                          \
0230       }                                                                                                                \
0231     } _PS_V1_INTERNAL_FACTORY_REGISTER_CNAME( s_##type, serial );                                                      \
0232   }
0233 
0234 #define _PS_V1_INTERNAL_DECLARE_FACTORY( type, id, factory, serial )                                                   \
0235   _PS_V1_INTERNAL_DECLARE_FACTORY_WITH_CREATOR( type, ::Gaudi::PluginService::v1::Details::Factory<type>, id, factory, \
0236                                                 serial )
0237 
0238 #endif //_GAUDI_PLUGIN_SERVICE_DETAILS_H_