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 <memory>
28 #include <string>
29 
30 namespace cet {
31  class PluginFactory;
32 }
33 
35 public:
37  std::string const& suffix = "plugin");
38 
39  // Provide a string or function giving the release and version of the
40  // plugin (default "Unknown").
41  void setDiagReleaseVersion(std::string const& rv);
42  void setDiagReleaseVersion(std::function<std::string()> rvf);
43 
44  // General function to find and call a named function from the
45  // specified plugin library. RESULT_TYPE must be specified; ARGS may
46  // be deduced.
47  template <typename RESULT_TYPE, typename... ARGS>
48  RESULT_TYPE call(std::string const& libspec,
49  std::string const& funcname,
50  ARGS&&... args) const;
51 
52  // Nothrow tag (see find(), below).
54 
55  // General functions to find and return a pointer to a function of the
56  // specified name and type. Use "nothrow" to select the non-throwing
57  // version of the function.
58  template <typename RESULT_TYPE, typename... ARGS>
59  auto find(std::string const& funcname, std::string const& libspec) const
60  -> RESULT_TYPE (*)(ARGS...);
61 
62  template <typename RESULT_TYPE, typename... ARGS>
63  auto find(std::string const& funcname,
64  std::string const& libspec,
65  LibraryManager::nothrow_t) const -> RESULT_TYPE (*)(ARGS...);
66 
67  template <typename FUNCTION_TYPE>
68  std::enable_if_t<std::is_function<FUNCTION_TYPE>::value, FUNCTION_TYPE*> find(
69  std::string const& funcname,
70  std::string const& libspec) const;
71 
72  // May define subclasses.
73  virtual ~PluginFactory() = default;
74 
75 private:
76  // Not copyable.
77  PluginFactory(PluginFactory const&) = delete;
78  PluginFactory& operator=(PluginFactory const&) = delete;
79 
80  template <typename T>
81  void resolveSymbolOrThrow_(std::string const& libspec,
82  std::string const& funcname,
83  T& symbol) const;
84 
85  std::string releaseVersion_() const;
86 
89  std::function<std::string()> releaseVersionFunc_{};
90 };
91 
92 inline void
94 {
95  releaseVersionFunc_ = rvf;
96 }
97 
98 inline void
100 {
102 }
103 
104 template <typename RESULT_TYPE, typename... ARGS>
105 inline RESULT_TYPE
107  std::string const& funcname,
108  ARGS&&... args) const
109 {
110  return (*find<RESULT_TYPE, ARGS...>(libspec, funcname))(
111  std::forward<ARGS>(args)...);
112 }
113 
114 template <typename FUNCTION_TYPE>
117  std::string const& funcname) const
118 {
119  FUNCTION_TYPE** symbol{nullptr};
120  resolveSymbolOrThrow_(libspec, funcname, symbol);
121  return *symbol;
122 }
123 
124 template <typename RESULT_TYPE, typename... ARGS>
125 inline auto
127  std::string const& funcname) const
128  -> RESULT_TYPE (*)(ARGS...)
129 {
130  RESULT_TYPE (*symbol)(ARGS...) = nullptr;
131  resolveSymbolOrThrow_(libspec, funcname, symbol);
132  return symbol;
133 }
134 
135 template <typename RESULT_TYPE, typename... ARGS>
136 inline auto
138  std::string const& funcname,
140  -> RESULT_TYPE (*)(ARGS...)
141 {
142  return lm_.getSymbolByLibspec<RESULT_TYPE (*)(ARGS...)>(
143  libspec, funcname, nothrow);
144 }
145 
146 template <typename T>
147 void
149  std::string const& funcname,
150  T& symbol) const
151 {
152  try {
153  lm_.getSymbolByLibspec(libspec, funcname, symbol);
154  }
155  catch (exception const& e) {
157  e, "Plugin", libspec, releaseVersion_());
158  }
159  if (symbol == nullptr) {
160  throw exception("Configuration", "BadPluginLibrary")
161  << "Plugin " << libspec << " with version " << releaseVersion_()
162  << " has internal symbol definition problems: consult an expert.";
163  }
164 }
165 #endif /* cetlib_PluginFactory_h */
166 
167 // Local Variables:
168 // mode: c++
169 // End:
RESULT_TYPE call(std::string const &libspec, std::string const &funcname, ARGS &&...args) const
std::function< std::string()> releaseVersionFunc_
Definition: PluginFactory.h:89
void resolveSymbolOrThrow_(std::string const &libspec, std::string const &funcname, T &symbol) const
::xsd::cxx::tree::exception< char > exception
Definition: Database.h:225
static LibraryManager::nothrow_t nothrow
Definition: PluginFactory.h:53
std::string releaseVersion_() const
LibraryManager lm_
Definition: PluginFactory.h:87
T getSymbolByLibspec(std::string const &libspec, std::string const &sym_name) const
const XML_Char int const XML_Char * value
Definition: expat.h:331
void setDiagReleaseVersion(std::string const &rv)
Definition: PluginFactory.h:99
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")
double T
Definition: Xdiff_gwt.C:5
Float_t e
Definition: plot.C:35
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:88
enum BeamMode string