Plugin.h
1 /*
2  * Copyright (C) 2006-2013 Marc Boris Duerner
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef Pt_Plugin_h
30 #define Pt_Plugin_h
31 
32 #include <Pt/System/Api.h>
33 #include <Pt/System/SystemError.h>
34 #include <Pt/System/Library.h>
35 #include <typeinfo>
36 #include <list>
37 #include <map>
38 #include <string>
39 
40 namespace Pt {
41 
42 namespace System {
43 
46 class PluginId
47 {
48  public:
51  PluginId(const std::type_info& iface)
52  : _iface(&iface)
53  { }
54 
57  virtual ~PluginId()
58  { }
59 
62  const std::type_info& iface() const
63  { return *_iface; }
64 
67  virtual const char* feature() const = 0;
68 
71  virtual const char* info() const = 0;
72 
73  private:
74  const std::type_info* _iface;
75 };
76 
79 template <typename Iface>
80 class Plugin : public PluginId
81 {
82  public:
86  : PluginId( typeid(Iface) )
87  { }
88 
91  virtual Iface* create() = 0;
92 
95  virtual void destroy(Iface* instance) = 0;
96 };
97 
98 
114 template <typename Class, typename Iface>
115 class BasicPlugin : public Plugin<Iface> {
116  public:
119  BasicPlugin(const std::string& feature, const std::string& info = std::string())
120  : Plugin<Iface>()
121  , _feature(feature)
122  , _info(info)
123  { }
124 
125  // inherit docs
126  Iface* create()
127  { return new Class; }
128 
129  // inherit docs
130  void destroy(Iface* instance)
131  { delete instance; }
132 
133  // inherit docs
134  virtual const char* feature() const
135  { return _feature.c_str(); }
136 
137  // inherit docs
138  virtual const char* info() const
139  { return _info.c_str(); }
140 
141  private:
142  std::string _feature;
143  std::string _info;
144 };
145 
148 template < typename IfaceT, typename PluginT = Plugin<IfaceT> >
150 {
151  public:
152  typedef typename std::multimap< std::string, PluginT* > PluginMap;
153  typedef typename std::multimap< IfaceT*, PluginT* > InstanceMap;
154 
157  class Iterator
158  {
159  public:
163  {}
164 
166  Iterator(typename PluginMap::const_iterator it)
167  : _it( it)
168  {}
169 
172  { ++_it; return *this; }
173 
175  const PluginId& operator*() const
176  { return *(_it->second); }
177 
179  const PluginId* operator->() const
180  { return _it->second; }
181 
183  bool operator==(const Iterator& it) const
184  { return _it == it._it; }
185 
187  bool operator!=(const Iterator& it) const
188  { return _it != it._it; }
189 
191  typename PluginMap::const_iterator _it;
192  };
193 
194  public:
198  : _iface( typeid(IfaceT) )
199  { }
200 
203  ~PluginManager();
204 
207  void loadPlugin(const std::string& sym, const Path& path);
208 
211  void registerPlugin(PluginT& plugin);
212 
215  void unregisterPlugin(PluginT& plugin);
216 
219  IfaceT* create(const std::string& feature);
220 
223  IfaceT* create(const Iterator& feature);
224 
227  void destroy(IfaceT* inst);
228 
231  Iterator begin() const
232  { return Iterator( _plugins.begin() ); }
233 
236  Iterator end() const
237  { return Iterator( _plugins.end() ); }
238 
239  protected:
241  PluginMap& plugins()
242  { return _plugins; }
243 
245  InstanceMap& instances()
246  { return _instances; }
247 
248  private:
250  const std::type_info& _iface;
251 
253  std::list<Library> _libs;
254 
256  PluginMap _plugins;
257 
259  InstanceMap _instances;
260 };
261 
262 
263 template <class IfaceT, typename PluginT >
265 {
266  // Destroy all instances. If any are left its actually a bug.
267  for(typename InstanceMap::iterator it = _instances.begin(); it != _instances.end(); ++it)
268  {
269  it->second->destroy( it->first );
270  }
271  _instances.clear();
272 }
273 
274 
275 template <class IfaceT, typename PluginT >
276 void PluginManager<IfaceT, PluginT>::loadPlugin(const std::string& sym, const Path& path)
277 {
278  Library shlib(path);
279 
280  void* symbol = shlib.resolve( sym.c_str() );
281  if( ! symbol )
282  return;
283 
284  PluginId** plugins = (PluginId**) symbol;
285 
286  for(; *plugins != 0; ++plugins)
287  {
288  if( (*plugins)->iface() == _iface )
289  {
290  PluginT* p = (PluginT*)(*plugins);
291  this->registerPlugin(*p);
292  }
293  }
294 
295  _libs.push_back(shlib);
296 }
297 
298 
299 template <class IfaceT, typename PluginT >
301 {
302  typename PluginMap::value_type p(plugin.feature(), &plugin);
303  _plugins.insert(p);
304 }
305 
306 
307 template <class IfaceT, typename PluginT >
309 {
310  typename PluginMap::iterator it = _plugins.find( plugin.feature() );
311  if( it != _plugins.end() )
312  {
313  _plugins.erase(it);
314  }
315 }
316 
317 
318 template <class IfaceT, typename PluginT >
319 IfaceT* PluginManager<IfaceT, PluginT>::create(const std::string& feature)
320 {
321  typename PluginMap::iterator it = _plugins.find(feature);
322  if( it == _plugins.end() )
323  {
324  return 0;
325  }
326 
327  PluginT* plugin = it->second;
328  IfaceT* iface = plugin->create();
329  if(iface)
330  {
331  typename InstanceMap::value_type elem(iface, plugin);
332  _instances.insert( elem );
333  }
334 
335  return iface;
336 }
337 
338 
339 template <class IfaceT, typename PluginT >
341 {
342  typename PluginMap::const_iterator it = pit._it;
343 
344  PluginT* plugin = it->second;
345  IfaceT* iface = plugin->create();
346  if(iface)
347  {
348  _instances.insert( std::make_pair(iface, plugin) );
349  }
350 
351  return iface;
352 }
353 
354 
355 template <class IfaceT, typename PluginT >
357 {
358  typename InstanceMap::iterator it = _instances.find(inst);
359  if( it == _instances.end() )
360  {
361  throw SystemError("plugin destroy");
362  }
363 
364  it->second->destroy(inst);
365  _instances.erase(it);
366  return;
367 }
368 
369 } // namespace System
370 
371 } // namespace Pt
372 
373 #endif // Pt_Plugin_h
Iterator end() const
End of loaded plugins.
Definition: Plugin.h:236
Manages loaded plugins.
Definition: Plugin.h:149
BasicPlugin(const std::string &feature, const std::string &info=std::string())
Constructs with feature string and info.
Definition: Plugin.h:119
Iterator for loaded plugins.
Definition: Plugin.h:157
virtual const char * feature() const =0
Returns the plugin feature string.
virtual const char * feature() const
Returns the plugin feature string.
Definition: Plugin.h:134
Plugin()
Default Constructor.
Definition: Plugin.h:85
virtual const char * info() const =0
Returns the plugin info string.
void loadPlugin(const std::string &sym, const Path &path)
Loads plugins from a library.
Definition: Plugin.h:276
Represents a path in the file-system.
Definition: Path.h:47
IfaceT * create(const std::string &feature)
Creates an instance by name.
Definition: Plugin.h:319
Interface for plugins.
Definition: Plugin.h:80
ID for plugin exports.
Definition: Plugin.h:46
~PluginManager()
Destructor.
Definition: Plugin.h:264
Iterator()
Default Constructor.
Definition: Plugin.h:162
virtual Iface * create()=0
Creates an instance.
void destroy(IfaceT *inst)
Destroys an instance.
Definition: Plugin.h:356
const PluginId * operator->() const
Access iterator value.
Definition: Plugin.h:179
Exception class indication a system error.
Definition: SystemError.h:42
bool operator!=(const Iterator &it) const
Comparison operator.
Definition: Plugin.h:187
A plugin implementation.
Definition: Plugin.h:115
Shared library loader.
Definition: Library.h:106
virtual const char * info() const
Returns the plugin info string.
Definition: Plugin.h:138
virtual void destroy(Iface *instance)=0
Destroys an instance.
PluginManager()
Default Constructor.
Definition: Plugin.h:197
PluginId(const std::type_info &iface)
Construct with type info of plugin interface.
Definition: Plugin.h:51
void * resolve(const char *symbol) const
Resolves the symbol symbol from the shared library Returns the address of the symbol or 0 if it was n...
virtual ~PluginId()
Destructor.
Definition: Plugin.h:57
Iterator begin() const
Begin of loaded plugins.
Definition: Plugin.h:231
bool operator==(const Iterator &it) const
Comparison operator.
Definition: Plugin.h:183
Iterator & operator++()
Advances the iterator.
Definition: Plugin.h:171
Iface * create()
Creates an instance.
Definition: Plugin.h:126
const PluginId & operator*() const
Access iterator value.
Definition: Plugin.h:175
void unregisterPlugin(PluginT &plugin)
Unregisters a plugin.
Definition: Plugin.h:308
void registerPlugin(PluginT &plugin)
Registers a plugin.
Definition: Plugin.h:300
void destroy(Iface *instance)
Destroys an instance.
Definition: Plugin.h:130
const std::type_info & iface() const
Returns the type of the plugin interface.
Definition: Plugin.h:62