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  friend class PluginManager;
160 
161  public:
165  {}
166 
168  Iterator(typename PluginMap::const_iterator it)
169  : _it( it)
170  {}
171 
174  { ++_it; return *this; }
175 
177  const PluginId& operator*() const
178  { return *(_it->second); }
179 
181  const PluginId* operator->() const
182  { return _it->second; }
183 
185  bool operator==(const Iterator& it) const
186  { return _it == it._it; }
187 
189  bool operator!=(const Iterator& it) const
190  { return _it != it._it; }
191 
192  private:
194  typename PluginMap::const_iterator _it;
195  };
196 
197  public:
201  : _iface( typeid(IfaceT) )
202  { }
203 
205  : _iface( typeid(IfaceT) )
206  {
207  if( ! plugins)
208  return;
209 
210  for(; *plugins != 0; ++plugins)
211  {
212  if( (*plugins)->iface() == _iface )
213  {
214  PluginT* p = (PluginT*)(*plugins);
215  this->registerPlugin(*p);
216  }
217  }
218  }
219 
222  ~PluginManager();
223 
226  void loadPlugin(const std::string& sym, const Path& path);
227 
230  void registerPlugin(PluginT& plugin);
231 
234  void unregisterPlugin(PluginT& plugin);
235 
238  IfaceT* create(const std::string& feature);
239 
242  IfaceT* create(const Iterator& feature);
243 
246  void destroy(IfaceT* inst);
247 
250  Iterator begin() const
251  { return Iterator( _plugins.begin() ); }
252 
255  Iterator end() const
256  { return Iterator( _plugins.end() ); }
257 
258  protected:
260  PluginMap& plugins()
261  { return _plugins; }
262 
264  InstanceMap& instances()
265  { return _instances; }
266 
267  private:
269  const std::type_info& _iface;
270 
272  std::list<Library> _libs;
273 
275  PluginMap _plugins;
276 
278  InstanceMap _instances;
279 };
280 
281 
282 template <class IfaceT, typename PluginT >
284 {
285  // Destroy all instances. If any are left its actually a bug.
286  for(typename InstanceMap::iterator it = _instances.begin(); it != _instances.end(); ++it)
287  {
288  it->second->destroy( it->first );
289  }
290  _instances.clear();
291 }
292 
293 
294 template <class IfaceT, typename PluginT >
295 void PluginManager<IfaceT, PluginT>::loadPlugin(const std::string& sym, const Path& path)
296 {
297  Library shlib(path);
298 
299  void* symbol = shlib.resolve( sym.c_str() );
300  if( ! symbol )
301  return;
302 
303  PluginId** plugins = (PluginId**) symbol;
304 
305  for(; *plugins != 0; ++plugins)
306  {
307  if( (*plugins)->iface() == _iface )
308  {
309  PluginT* p = (PluginT*)(*plugins);
310  this->registerPlugin(*p);
311  }
312  }
313 
314  _libs.push_back(shlib);
315 }
316 
317 
318 template <class IfaceT, typename PluginT >
320 {
321  typename PluginMap::value_type p(plugin.feature(), &plugin);
322  _plugins.insert(p);
323 }
324 
325 
326 template <class IfaceT, typename PluginT >
328 {
329  typename PluginMap::iterator it = _plugins.find( plugin.feature() );
330  if( it != _plugins.end() )
331  {
332  _plugins.erase(it);
333  }
334 }
335 
336 
337 template <class IfaceT, typename PluginT >
338 IfaceT* PluginManager<IfaceT, PluginT>::create(const std::string& feature)
339 {
340  typename PluginMap::iterator it = _plugins.find(feature);
341  if( it == _plugins.end() )
342  {
343  return 0;
344  }
345 
346  PluginT* plugin = it->second;
347  IfaceT* iface = plugin->create();
348  if(iface)
349  {
350  typename InstanceMap::value_type elem(iface, plugin);
351  _instances.insert( elem );
352  }
353 
354  return iface;
355 }
356 
357 
358 template <class IfaceT, typename PluginT >
360 {
361  typename PluginMap::const_iterator it = pit._it;
362 
363  PluginT* plugin = it->second;
364  IfaceT* iface = plugin->create();
365  if(iface)
366  {
367  _instances.insert( std::make_pair(iface, plugin) );
368  }
369 
370  return iface;
371 }
372 
373 
374 template <class IfaceT, typename PluginT >
376 {
377  typename InstanceMap::iterator it = _instances.find(inst);
378  if( it == _instances.end() )
379  {
380  throw SystemError("plugin destroy");
381  }
382 
383  it->second->destroy(inst);
384  _instances.erase(it);
385  return;
386 }
387 
388 } // namespace System
389 
390 } // namespace Pt
391 
392 #endif // Pt_Plugin_h
Iterator end() const
End of loaded plugins.
Definition: Plugin.h:255
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:295
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:338
Interface for plugins.
Definition: Plugin.h:80
ID for plugin exports.
Definition: Plugin.h:46
~PluginManager()
Destructor.
Definition: Plugin.h:283
Iterator()
Default Constructor.
Definition: Plugin.h:164
virtual Iface * create()=0
Creates an instance.
void destroy(IfaceT *inst)
Destroys an instance.
Definition: Plugin.h:375
const PluginId * operator->() const
Access iterator value.
Definition: Plugin.h:181
Exception class indication a system error.
Definition: SystemError.h:42
bool operator!=(const Iterator &it) const
Comparison operator.
Definition: Plugin.h:189
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:200
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:250
bool operator==(const Iterator &it) const
Comparison operator.
Definition: Plugin.h:185
Iterator & operator++()
Advances the iterator.
Definition: Plugin.h:173
Iface * create()
Creates an instance.
Definition: Plugin.h:126
const PluginId & operator*() const
Access iterator value.
Definition: Plugin.h:177
void unregisterPlugin(PluginT &plugin)
Unregisters a plugin.
Definition: Plugin.h:327
void registerPlugin(PluginT &plugin)
Registers a plugin.
Definition: Plugin.h:319
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