PluginFactory.h
Go to the documentation of this file.
1 #ifndef cetlib_PluginFactory_h
2 #define cetlib_PluginFactory_h
3 ////////////////////////////////////////////////////////////////////////
4 // PluginFactory.
5 //
6 // General facility for managing the loading and creation of plugins.
7 //
8 // One can use this class directly; however one is encouraged to use a
9 // subclass (e.g.cet::BasicPluginFactory) which provides convenient
10 // facilities for managing plugins that conform to a particular pattern.
11 //
12 // One is expected (but not mandated) to call setDiagReleaseVersion() to
13 // allow to PluginFactory to provide more information about the plugin
14 // in the event of a failure. In a future enhancement this will likely
15 // be obtained from the plugin library itself where available.
16 //
17 // Note that due to the nature of the C functions which find symbols in
18 // dynamic libraries, there is no type safety: a found symbol of the
19 // correct name will be coerced to the desired function type. If that
20 // type is inccorrect, chaos is likely to ensue.
21 ////////////////////////////////////////////////////////////////////////
22 
23 #include "cetlib/LibraryManager.h"
25 #include "cetlib_except/exception.h"
26 
27 #include <functional>
28 #include <string>
29 #include <type_traits>
30 
31 namespace cet {
32  class PluginFactory;
33 }
34 
36 public:
38  std::string const& suffix = "plugin");
39 
40  // Provide a string or function giving the release and version of the
41  // plugin (default "Unknown").
42  void setDiagReleaseVersion(std::string const& rv);
44 
45  // General function to find and call a named function from the
46  // specified plugin library. RESULT_TYPE must be specified; ARGS may
47  // be deduced.
48  template <typename RESULT_TYPE, typename... ARGS>
49  RESULT_TYPE call(std::string const& libspec,
50  std::string const& funcname,
51  ARGS&&... args) const;
52 
53  // Nothrow tag (see find(), below).
55 
56  // General functions to find and return a pointer to a function of the
57  // specified name and type. Use "nothrow" to select the non-throwing
58  // version of the function.
59  template <typename RESULT_TYPE, typename... ARGS>
60  auto find(std::string const& funcname, std::string const& libspec) const
61  -> RESULT_TYPE (*)(ARGS...);
62 
63  template <typename RESULT_TYPE, typename... ARGS>
64  auto find(std::string const& funcname,
65  std::string const& libspec,
66  LibraryManager::nothrow_t) const -> RESULT_TYPE (*)(ARGS...);
67 
68  template <typename FUNCTION_TYPE>
69  std::enable_if_t<std::is_function_v<FUNCTION_TYPE>, FUNCTION_TYPE*> find(
70  std::string const& funcname,
71  std::string const& libspec) const;
72 
73  // May define subclasses.
74  virtual ~PluginFactory() = default;
75 
76  // Not copyable.
77  PluginFactory(PluginFactory const&) = delete;
78  PluginFactory& operator=(PluginFactory const&) = delete;
79 
80 private:
81  template <typename T>
82  void resolveSymbolOrThrow_(std::string const& libspec,
83  std::string const& funcname,
84  T& symbol) const;
85 
86  std::string releaseVersion_() const;
87 
90  std::function<std::string()> releaseVersionFunc_{};
91 };
92 
93 inline void
95 {
96  releaseVersionFunc_ = rvf;
97 }
98 
99 inline void
101 {
103 }
104 
105 template <typename RESULT_TYPE, typename... ARGS>
106 inline RESULT_TYPE
108  std::string const& funcname,
109  ARGS&&... args) const
110 {
111  return (*find<RESULT_TYPE, ARGS...>(libspec, funcname))(
112  std::forward<ARGS>(args)...);
113 }
114 
115 template <typename FUNCTION_TYPE>
116 inline std::enable_if_t<std::is_function_v<FUNCTION_TYPE>, FUNCTION_TYPE*>
118  std::string const& funcname) const
119 {
120  FUNCTION_TYPE** symbol{nullptr};
121  resolveSymbolOrThrow_(libspec, funcname, symbol);
122  return *symbol;
123 }
124 
125 template <typename RESULT_TYPE, typename... ARGS>
126 inline auto
128  std::string const& funcname) const
129  -> RESULT_TYPE (*)(ARGS...)
130 {
131  RESULT_TYPE (*symbol)(ARGS...) = nullptr;
132  resolveSymbolOrThrow_(libspec, funcname, symbol);
133  return symbol;
134 }
135 
136 template <typename RESULT_TYPE, typename... ARGS>
137 inline auto
139  std::string const& funcname,
141  -> RESULT_TYPE (*)(ARGS...)
142 {
143  return lm_.getSymbolByLibspec<RESULT_TYPE (*)(ARGS...)>(
144  libspec, funcname, nothrow);
145 }
146 
147 template <typename T>
148 void
150  std::string const& funcname,
151  T& symbol) const
152 {
153  try {
154  lm_.getSymbolByLibspec(libspec, funcname, symbol);
155  }
156  catch (exception const& e) {
158  e, "Plugin", libspec, releaseVersion_());
159  }
160  if (symbol == nullptr) {
161  throw exception("Configuration", "BadPluginLibrary")
162  << "Plugin " << libspec << " with version " << releaseVersion_()
163  << " has internal symbol definition problems: consult an expert.";
164  }
165 }
166 #endif /* cetlib_PluginFactory_h */
167 
168 // Local Variables:
169 // mode: c++
170 // End:
RESULT_TYPE call(std::string const &libspec, std::string const &funcname, ARGS &&...args) const
std::string string
Definition: nybbler.cc:12
std::function< std::string()> releaseVersionFunc_
Definition: PluginFactory.h:90
void resolveSymbolOrThrow_(std::string const &libspec, std::string const &funcname, T &symbol) const
static LibraryManager::nothrow_t nothrow
Definition: PluginFactory.h:54
STL namespace.
std::string releaseVersion_() const
static QCString args
Definition: declinfo.cpp:674
LibraryManager lm_
Definition: PluginFactory.h:88
T getSymbolByLibspec(std::string const &libspec, std::string const &sym_name) const
const double e
void setDiagReleaseVersion(std::string const &rv)
auto find(std::string const &funcname, std::string const &libspec) const -> RESULT_TYPE(*)(ARGS...)
PluginFactory(cet::search_path const &search_path, std::string const &suffix="plugin")
Definition: PluginFactory.cc:5
void function(int client, int *resource, int parblock, int *test, int p)
void wrapLibraryManagerException(cet::exception const &e, std::string const &item_type, std::string const &libspec, std::string const &release)
std::string releaseVersionString_
Definition: PluginFactory.h:89
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33