PluginServiceDetails.h
Go to the documentation of this file.
1 #ifndef _GAUDI_PLUGIN_SERVICE_DETAILS_H_
2 #define _GAUDI_PLUGIN_SERVICE_DETAILS_H_
3 /*****************************************************************************\
4 * (c) Copyright 2013 CERN *
5 * *
6 * This software is distributed under the terms of the GNU General Public *
7 * Licence version 3 (GPL Version 3), copied verbatim in the file "LICENCE". *
8 * *
9 * In applying this licence, CERN does not waive the privileges and immunities *
10 * granted to it by virtue of its status as an Intergovernmental Organization *
11 * or submit itself to any jurisdiction. *
12 \*****************************************************************************/
13 
15 
16 #include <string>
17 #include <sstream>
18 #include <map>
19 #include <set>
20 #include <typeinfo>
21 #include <utility>
22 
23 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
24 #include <mutex>
25 #endif
26 
27 #if __GNUC__ >= 4
28 # define GAUDIPS_HASCLASSVISIBILITY
29 #endif
30 
31 #if defined(GAUDIPS_HASCLASSVISIBILITY)
32 # define GAUDIPS_IMPORT __attribute__((visibility("default")))
33 # define GAUDIPS_EXPORT __attribute__((visibility("default")))
34 # define GAUDIPS_LOCAL __attribute__((visibility("hidden")))
35 #else
36 # define GAUDIPS_IMPORT
37 # define GAUDIPS_EXPORT
38 # define GAUDIPS_LOCAL
39 #endif
40 
41 #ifdef GaudiPluginService_EXPORTS
42 #define GAUDIPS_API GAUDIPS_EXPORT
43 #else
44 #define GAUDIPS_API GAUDIPS_IMPORT
45 #endif
46 
47 namespace Gaudi { namespace PluginService {
48 
49  namespace Details {
54  template <class T>
55  class Factory {
56  public:
57 #if !defined(__REFLEX__) || defined(ATLAS)
58  template <typename S, typename... Args>
59  static typename S::ReturnType create(Args&&... args) {
60  return new T(std::forward<Args>(args)...);
61  }
62 #endif
63  };
64 
68  void* getCreator(const std::string& id, const std::string& type);
69 
82  template <typename F>
83  inline F getCreator(const std::string& id) {
84  union { void* src; F dst; } p2p;
85  p2p.src = getCreator(id, typeid(F).name());
86  return p2p.dst;
87  }
88 
93 
95  template <typename T>
96  inline std::string demangle() { return demangle(typeid(T)); }
97 
100  public:
102 
105 
106  struct FactoryInfo {
107  FactoryInfo(std::string lib, void* p=0,
108  std::string t="",
109  std::string rt="",
110  std::string cn="",
111  Properties props = Properties()):
112  library(std::move(lib)), ptr(p),
113  type(std::move(t)), rtype(std::move(rt)),
114  className(std::move(cn)), properties(std::move(props)) {}
115 
117  void* ptr;
121  Properties properties;
122 
123  FactoryInfo& addProperty(const KeyType& k, std::string v) {
124  properties[k] = std::move(v);
125  return *this;
126  }
127  };
128 
131 
133  static Registry& instance();
134 
136  template <typename F, typename T, typename I>
137  inline FactoryInfo& add(const I& id, typename F::FuncType ptr){
138  union { typename F::FuncType src; void* dst; } p2p;
139  p2p.src = ptr;
140  std::ostringstream o; o << id;
141  return add(o.str(), p2p.dst,
142  typeid(typename F::FuncType).name(),
143  typeid(typename F::ReturnType).name(),
144  demangle<T>());
145  }
146 
148  void* get(const std::string& id, const std::string& type) const;
149 
151  const FactoryInfo& getInfo(const std::string& id) const;
152 
154  Registry&
155  addProperty(const std::string& id,
156  const std::string& k,
157  const std::string& v);
158 
160  std::set<KeyType> loadedFactories() const;
161 
163  inline const FactoryMap& factories() const {
164  if (!m_initialized) const_cast<Registry*>(this)->initialize();
165  return m_factories;
166  }
167 
168  private:
173  Registry();
174 
176  Registry(const Registry&): m_initialized(false) {}
177 
179  FactoryInfo&
180  add(const std::string& id, void *factory,
181  const std::string& type, const std::string& rtype,
182  const std::string& className,
183  const Properties& props = Properties());
184 
186  inline FactoryMap& factories() {
187  if (!m_initialized) initialize();
188  return m_factories;
189  }
190 
193  void initialize();
194 
197 
199  FactoryMap m_factories;
200 
201 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
202  mutable std::recursive_mutex m_mutex;
204 #endif
205  };
206 
209  public:
210  enum Level { Debug=0, Info=1, Warning=2, Error=3 };
211  Logger(Level level = Warning): m_level(level) {}
212  virtual ~Logger() {}
213  inline Level level() const { return m_level; }
214  inline void setLevel(Level level) { m_level = level; }
215  inline void info(const std::string& msg) { report(Info, msg); }
216  inline void debug(const std::string& msg) { report(Debug, msg); }
217  inline void warning(const std::string& msg) { report(Warning, msg); }
218  inline void error(const std::string& msg) { report(Error, msg); }
219  private:
220  virtual void report(Level lvl, const std::string& msg);
222  };
223 
229  }
230 
232  GAUDIPS_API void SetDebug(int debugLevel);
234  GAUDIPS_API int Debug();
235 
236 }}
237 
238 #define _INTERNAL_FACTORY_REGISTER_CNAME(name, serial) \
239  _register_ ## _ ## serial
240 
241 #define _INTERNAL_DECLARE_FACTORY_WITH_CREATOR(type, typecreator, \
242  id, factory, serial) \
243  namespace { \
244  class _INTERNAL_FACTORY_REGISTER_CNAME(type, serial) { \
245  public: \
246  typedef factory s_t; \
247  typedef typecreator f_t; \
248  static s_t::FuncType creator() { return &f_t::create<s_t>; } \
249  _INTERNAL_FACTORY_REGISTER_CNAME(type, serial) () { \
250  using ::Gaudi::PluginService::Details::Registry; \
251  Registry::instance().add<s_t, type>(id, creator()); \
252  } \
253  } _INTERNAL_FACTORY_REGISTER_CNAME(s_ ## type, serial); \
254  }
255 
256 #define _INTERNAL_DECLARE_FACTORY(type, id, factory, serial) \
257  _INTERNAL_DECLARE_FACTORY_WITH_CREATOR(type, \
258  ::Gaudi::PluginService::Details::Factory<type>, \
259  id, factory, serial)
260 
261 #endif //_GAUDI_PLUGIN_SERVICE_DETAILS_H_
#define GAUDIPS_API
Registry(const Registry &)
Private copy constructor for the singleton pattern.
Class providing default factory functions.
STL namespace.
FactoryMap & factories()
Return the known factories (loading the list if not yet done).
std::vector< Gaudi::Details::PropertyBase * > Properties
Definition: PropertyMgr.h:139
GAUDIPS_API Logger & logger()
Return the current logger instance.
FactoryInfo & addProperty(const KeyType &k, std::string v)
std::map< KeyType, std::string > Properties
Type used for the properties implementation.
Simple logging class, just to provide a default implementation.
static S::ReturnType create(Args &&...args)
STL class.
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
FactoryInfo(std::string lib, void *p=0, std::string t="", std::string rt="", std::string cn="", Properties props=Properties())
GAUDIPS_API std::string demangle(const std::type_info &id)
Return a canonical name for type_info object (implementation borrowed from GaudiKernel/System).
const FactoryMap & factories() const
Return the known factories (loading the list if not yet done).
T move(T...args)
void warning(const std::string &msg)
STL class.
GAUDIPS_API void * getCreator(const std::string &id, const std::string &type)
Function used to load a specific factory function.
In-memory database of the loaded factories.
FactoryInfo & add(const I &id, typename F::FuncType ptr)
Add a factory to the database.
GAUDIPS_API int Debug()
Backward compatibility with Reflex.
GAUDIPS_API void setLogger(Logger *logger)
Set the logger instance to use.
std::map< KeyType, FactoryInfo > FactoryMap
Type used for the database implementation.
FactoryMap m_factories
Internal storage for factories.
Helper functions to set/get the application return code.
Definition: __init__.py:1
bool m_initialized
Flag recording if the registry has been initialized or not.