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
40namespace Pt {
41
42namespace System {
43
49{
50 public:
53 PluginId(const std::type_info& iface)
54 : _iface(&iface)
55 { }
56
59 virtual ~PluginId()
60 { }
61
64 const std::type_info& iface() const
65 { return *_iface; }
66
69 virtual const char* feature() const = 0;
70
73 virtual const char* info() const = 0;
74
75 private:
76 const std::type_info* _iface;
77};
78
96template <typename Iface>
97class Plugin : public PluginId
98{
99 public:
103 : PluginId( typeid(Iface) )
104 { }
105
108 virtual Iface* create() = 0;
109
112 virtual void destroy(Iface* instance) = 0;
113};
114
115
125template <typename Class, typename Iface>
126class BasicPlugin : public Plugin<Iface> {
127 public:
130 BasicPlugin(const std::string& feature, const std::string& info = std::string())
131 : Plugin<Iface>()
132 , _feature(feature)
133 , _info(info)
134 { }
135
136 // inherit docs
137 Iface* create()
138 { return new Class; }
139
140 // inherit docs
141 void destroy(Iface* instance)
142 { delete instance; }
143
144 // inherit docs
145 virtual const char* feature() const
146 { return _feature.c_str(); }
147
148 // inherit docs
149 virtual const char* info() const
150 { return _info.c_str(); }
151
152 private:
153 std::string _feature;
154 std::string _info;
155};
156
183template < typename IfaceT, typename PluginT = Plugin<IfaceT> >
185{
186 public:
187 typedef typename std::multimap< std::string, PluginT* > PluginMap;
188 typedef typename std::multimap< IfaceT*, PluginT* > InstanceMap;
189
193 {
194 friend class PluginManager;
195
196 public:
200 {}
201
203 Iterator(typename PluginMap::const_iterator it)
204 : _it( it)
205 {}
206
209 { ++_it; return *this; }
210
212 const PluginId& operator*() const
213 { return *(_it->second); }
214
216 const PluginId* operator->() const
217 { return _it->second; }
218
220 bool operator==(const Iterator& it) const
221 { return _it == it._it; }
222
224 bool operator!=(const Iterator& it) const
225 { return _it != it._it; }
226
227 private:
229 typename PluginMap::const_iterator _it;
230 };
231
232 public:
236 : _iface( typeid(IfaceT) )
237 { }
238
240 : _iface( typeid(IfaceT) )
241 {
242 if( ! plugins)
243 return;
244
245 for(; *plugins != 0; ++plugins)
246 {
247 if( (*plugins)->iface() == _iface )
248 {
249 PluginT* p = (PluginT*)(*plugins);
250 this->registerPlugin(*p);
251 }
252 }
253 }
254
258
261 void loadPlugin(const std::string& sym, const Path& path);
262
265 void registerPlugin(PluginT& plugin);
266
269 void unregisterPlugin(PluginT& plugin);
270
273 IfaceT* create(const std::string& feature);
274
277 IfaceT* create(const Iterator& feature);
278
281 void destroy(IfaceT* inst);
282
286 { return Iterator( _plugins.begin() ); }
287
290 Iterator end() const
291 { return Iterator( _plugins.end() ); }
292
293 protected:
295 PluginMap& plugins()
296 { return _plugins; }
297
299 InstanceMap& instances()
300 { return _instances; }
301
302 private:
304 const std::type_info& _iface;
305
307 std::list<Library> _libs;
308
310 PluginMap _plugins;
311
313 InstanceMap _instances;
314};
315
316
317template <class IfaceT, typename PluginT >
319{
320 // Destroy all instances. If any are left its actually a bug.
321 for(typename InstanceMap::iterator it = _instances.begin(); it != _instances.end(); ++it)
322 {
323 it->second->destroy( it->first );
324 }
325 _instances.clear();
326}
327
328
329template <class IfaceT, typename PluginT >
330void PluginManager<IfaceT, PluginT>::loadPlugin(const std::string& sym, const Path& path)
331{
332 Library shlib(path);
333
334 void* symbol = shlib.resolve( sym.c_str() );
335 if( ! symbol )
336 return;
337
338 PluginId** plugins = (PluginId**) symbol;
339
340 for(; *plugins != 0; ++plugins)
341 {
342 if( (*plugins)->iface() == _iface )
343 {
344 PluginT* p = (PluginT*)(*plugins);
345 this->registerPlugin(*p);
346 }
347 }
348
349 _libs.push_back(shlib);
350}
351
352
353template <class IfaceT, typename PluginT >
355{
356 typename PluginMap::value_type p(plugin.feature(), &plugin);
357 _plugins.insert(p);
358}
359
360
361template <class IfaceT, typename PluginT >
363{
364 typename PluginMap::iterator it = _plugins.find( plugin.feature() );
365 if( it != _plugins.end() )
366 {
367 _plugins.erase(it);
368 }
369}
370
371
372template <class IfaceT, typename PluginT >
373IfaceT* PluginManager<IfaceT, PluginT>::create(const std::string& feature)
374{
375 typename PluginMap::iterator it = _plugins.find(feature);
376 if( it == _plugins.end() )
377 {
378 return 0;
379 }
380
381 PluginT* plugin = it->second;
382 IfaceT* iface = plugin->create();
383 if(iface)
384 {
385 typename InstanceMap::value_type elem(iface, plugin);
386 _instances.insert( elem );
387 }
388
389 return iface;
390}
391
392
393template <class IfaceT, typename PluginT >
395{
396 typename PluginMap::const_iterator it = pit._it;
397
398 PluginT* plugin = it->second;
399 IfaceT* iface = plugin->create();
400 if(iface)
401 {
402 _instances.insert( std::make_pair(iface, plugin) );
403 }
404
405 return iface;
406}
407
408
409template <class IfaceT, typename PluginT >
411{
412 typename InstanceMap::iterator it = _instances.find(inst);
413 if( it == _instances.end() )
414 {
415 throw SystemError("plugin destroy");
416 }
417
418 it->second->destroy(inst);
419 _instances.erase(it);
420 return;
421}
422
423} // namespace System
424
425} // namespace Pt
426
427#endif // Pt_Plugin_h
virtual const char * feature() const
Returns the plugin feature string.
Definition Plugin.h:145
BasicPlugin(const std::string &feature, const std::string &info=std::string())
Constructs with feature string and info.
Definition Plugin.h:130
Iface * create()
Creates an instance.
Definition Plugin.h:137
virtual const char * info() const
Returns the plugin info string.
Definition Plugin.h:149
void destroy(Iface *instance)
Destroys an instance.
Definition Plugin.h:141
Shared library loader.
Definition Library.h:123
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...
Represents a path in the file-system.
Definition Path.h:48
ID for plugin exports.
Definition Plugin.h:49
virtual ~PluginId()
Destructor.
Definition Plugin.h:59
virtual const char * feature() const =0
Returns the plugin feature string.
PluginId(const std::type_info &iface)
Construct with type info of plugin interface.
Definition Plugin.h:53
virtual const char * info() const =0
Returns the plugin info string.
const std::type_info & iface() const
Returns the type of the plugin interface.
Definition Plugin.h:64
Iterator for loaded plugins.
Definition Plugin.h:193
const PluginId * operator->() const
Access iterator value.
Definition Plugin.h:216
bool operator!=(const Iterator &it) const
Comparison operator.
Definition Plugin.h:224
Iterator()
Default Constructor.
Definition Plugin.h:199
const PluginId & operator*() const
Access iterator value.
Definition Plugin.h:212
bool operator==(const Iterator &it) const
Comparison operator.
Definition Plugin.h:220
Iterator & operator++()
Advances the iterator.
Definition Plugin.h:208
Iterator begin() const
Begin of loaded plugins.
Definition Plugin.h:285
void loadPlugin(const std::string &sym, const Path &path)
Loads plugins from a library.
Definition Plugin.h:330
void unregisterPlugin(PluginT &plugin)
Unregisters a plugin.
Definition Plugin.h:362
Iterator end() const
End of loaded plugins.
Definition Plugin.h:290
void registerPlugin(PluginT &plugin)
Registers a plugin.
Definition Plugin.h:354
PluginManager()
Default Constructor.
Definition Plugin.h:235
void destroy(IfaceT *inst)
Destroys an instance.
Definition Plugin.h:410
IfaceT * create(const std::string &feature)
Creates an instance by name.
Definition Plugin.h:373
~PluginManager()
Destructor.
Definition Plugin.h:318
virtual Iface * create()=0
Creates an instance.
virtual void destroy(Iface *instance)=0
Destroys an instance.
Plugin()
Default Constructor.
Definition Plugin.h:102
SystemError(const std::string &what)
Construct with error message.
System programming
Definition Connection.h:26
Core module.
Definition Allocator.h:33