The Gaudi Framework  master (d98a2936)
PluginServiceDetailsV2.h
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 2013-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #pragma once
12 
14 
16 
17 #include <any>
18 #include <functional>
19 #include <map>
20 #include <memory>
21 #include <mutex>
22 #include <set>
23 #include <sstream>
24 #include <string>
25 #include <typeinfo>
26 #include <utility>
27 
28 namespace Gaudi {
29  namespace PluginService {
32  template <typename>
33  struct Factory;
35 
37  namespace Details {
38  template <typename>
39  struct Traits;
40 
41  template <typename R, typename... Args>
42  struct Traits<R( Args... )> {
43  using ReturnType = std::unique_ptr<std::remove_pointer_t<R>>;
44  using FactoryType = std::function<ReturnType( Args... )>;
45  };
46 
50  std::string demangle( const std::type_info& id );
51 
53  template <typename T>
54  inline std::string demangle() {
55  return demangle( typeid( T ) );
56  }
57 
59  template <typename ID>
60  inline std::string stringify_id( const ID& id ) {
61  std::ostringstream o;
62  o << id;
63  return o.str();
64  }
66  template <>
67  inline std::string stringify_id<std::string>( const std::string& id ) {
68  return id;
69  }
70 
72  void reportBadAnyCast( const std::type_info& factory_type, const std::string& id );
73 
75  class GAUDIPS_API Logger {
76  public:
77  enum Level { Debug = 0, Info = 1, Warning = 2, Error = 3 };
78  Logger( Level level = Warning ) : m_level( level ) {}
79  virtual ~Logger() {}
80  inline Level level() const { return m_level; }
81  inline void setLevel( Level level ) { m_level = level; }
82  inline void info( const std::string& msg ) { report( Info, msg ); }
83  inline void debug( const std::string& msg ) { report( Debug, msg ); }
84  inline void warning( const std::string& msg ) { report( Warning, msg ); }
85  inline void error( const std::string& msg ) { report( Error, msg ); }
86 
87  private:
88  virtual void report( Level lvl, const std::string& msg );
89  Level m_level;
90  };
91 
93  GAUDIPS_API Logger& logger();
96  GAUDIPS_API void setLogger( Logger* logger );
97 
99  class GAUDIPS_API Registry {
100  public:
101  using KeyType = std::string;
102 
104  using Properties = std::map<KeyType, std::string>;
105 
106  struct FactoryInfo {
107  std::string library;
108  std::any factory{};
110 
111  inline bool is_set() const { return factory.has_value(); }
112  Properties::mapped_type getprop( const Properties::key_type& name ) const;
113  };
114 
116  using FactoryMap = std::map<KeyType, FactoryInfo>;
117 
119  template <typename F>
120  F get( const KeyType& id ) {
121  const FactoryInfo& info = Registry::instance().getInfo( id, true );
122 
123  // Check if factory has been marked as deprecated.
124  const auto& prop = info.properties.find( "deprecated" );
125  if ( prop != info.properties.end() ) {
126  std::string msg = "factory '" + info.getprop( "ClassName" ) + "' is deprecated" +
127  ( prop->second.empty() ? "" : ( ": " + prop->second ) );
128  if ( m_werror.find( "deprecated" ) != m_werror.end() ) {
129  logger().error( msg );
130  return std::any_cast<F>( std::any() );
131  } else {
132  logger().warning( msg );
133  }
134  }
135 
136 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
137  if ( !info.getprop( "ReflexName" ).empty() ) {
138  const std::string real_name = info.getprop( "ClassName" );
139  logger().warning( "requesting factory via old name '" + id + "' use '" +
140  ( real_name.empty() ? "<undefined>" : real_name ) + "' instead" );
141  }
142 #endif
143  return std::any_cast<F>( info.factory );
144  }
145 
147  static Registry& instance();
148 
150  FactoryInfo& add( const KeyType& id, FactoryInfo info );
151 
153  FactoryMap::size_type erase( const KeyType& id );
154 
156  const FactoryInfo& getInfo( const KeyType& id, const bool load = false ) const;
157 
159  Registry& addProperty( const KeyType& id, const KeyType& k, const std::string& v );
160 
162  void setError( const KeyType& warning );
163 
165  void unsetError( const KeyType& warning );
166 
168  std::set<KeyType> loadedFactoryNames() const;
169 
175  const FactoryMap& factories() const;
176 
177  private:
179  Registry();
180 
182  Registry( const Registry& ) = delete;
183 
185  FactoryMap& factories();
186 
189  void initialize();
190 
191  bool tryDLOpen( const std::string_view& ) const;
192 
194  mutable std::once_flag m_initialized;
195 
197  FactoryMap m_factories;
198 
200  std::set<KeyType> m_werror;
201 
203  mutable std::recursive_mutex m_mutex;
204  };
205 
210  template <typename, typename>
211  struct DefaultFactory;
212  template <typename T, typename R, typename... Args>
213  struct DefaultFactory<T, Factory<R( Args... )>> {
214  inline typename Factory<R( Args... )>::ReturnType operator()( Args... args ) {
215  return std::make_unique<T>( std::move( args )... );
216  }
217  };
218 
222  std::string getDSONameFor( void* fptr );
223  } // namespace Details
224 
226  GAUDIPS_API void SetDebug( int debugLevel );
228  GAUDIPS_API int Debug();
229  }
230  } // namespace PluginService
231 } // namespace Gaudi
232 
233 #define _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME_TOKEN( serial ) _register_##serial
234 #define _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME( serial ) \
235  _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME_TOKEN( serial )
236 #define _PS_V2_INTERNAL_FACTORY_REGISTER_CNAME _PS_V2_INTERNAL_FACTORY_MAKE_REGISTER_CNAME( __LINE__ )
Gaudi::PluginService::v2::Details::reportBadAnyCast
void reportBadAnyCast(const std::type_info &factory_type, const std::string &id)
Definition: PluginServiceV2.cpp:116
Gaudi::PluginService::v2::SetDebug
void SetDebug(int debugLevel)
Definition: PluginServiceV2.cpp:324
GAUDI_PLUGIN_SERVICE_V2_INLINE
#define GAUDI_PLUGIN_SERVICE_V2_INLINE
Definition: PluginServiceCommon.h:17
GaudiPartProp.decorators.get
get
decorate the vector of properties
Definition: decorators.py:283
GaudiMP.FdsRegistry.msg
msg
Definition: FdsRegistry.py:19
GaudiPartProp.tests.id
id
Definition: tests.py:111
Properties
Definition: Properties.py:1
Gaudi::PluginService::v2::Details::setLogger
void setLogger(Logger *logger)
Definition: PluginServiceV2.cpp:304
GaudiPartProp.tests.v2
v2
Definition: tests.py:59
Gaudi::PluginService::v2::Details::getDSONameFor
std::string getDSONameFor(void *fptr)
Definition: PluginServiceV2.cpp:307
Gaudi::Details::Property::ParsingErrorPolicy::Warning
@ Warning
cpluginsvc.factories
def factories()
Definition: cpluginsvc.py:93
gaudirun.level
level
Definition: gaudirun.py:364
Gaudi
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition: __init__.py:1
gaudiComponentHelp.properties
properties
Definition: gaudiComponentHelp.py:68
Gaudi::PluginService::v2::Details::logger
Logger & logger()
Definition: PluginServiceV2.cpp:303
Gaudi::PluginService::v2::Debug
int Debug()
Definition: PluginServiceV2.cpp:335
MSG::Level
Level
Definition: IMessageSvc.h:22
ConditionsStallTest.name
name
Definition: ConditionsStallTest.py:77
gaudirun.args
args
Definition: gaudirun.py:336
GAUDIPS_API
#define GAUDIPS_API
Definition: PluginServiceCommon.h:42
Properties.v
v
Definition: Properties.py:122
GaudiPython.Persistency.add
def add(instance)
Definition: Persistency.py:50
Gaudi::PluginService::v2::Details::demangle
std::string demangle(const std::string &id)
Definition: PluginServiceV2.cpp:87
PluginServiceCommon.h