00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_PLUGINMANAGER_HEADER__
00011 #define __PION_PLUGINMANAGER_HEADER__
00012
00013 #include <map>
00014 #include <string>
00015 #include <boost/cstdint.hpp>
00016 #include <boost/function.hpp>
00017 #include <boost/function/function1.hpp>
00018 #include <boost/thread/mutex.hpp>
00019 #include <pion/PionConfig.hpp>
00020 #include <pion/PionException.hpp>
00021 #include <pion/PionPlugin.hpp>
00022
00023
00024 namespace pion {
00025
00029 template <typename PLUGIN_TYPE>
00030 class PluginManager
00031 {
00032 public:
00033
00035 class PluginNotFoundException : public PionException {
00036 public:
00037 PluginNotFoundException(const std::string& plugin_id)
00038 : PionException("No plug-ins found for identifier: ", plugin_id) {}
00039 };
00040
00042 class DuplicatePluginException : public PionException {
00043 public:
00044 DuplicatePluginException(const std::string& plugin_id)
00045 : PionException("A plug-in already exists for identifier: ", plugin_id) {}
00046 };
00047
00049 typedef boost::function1<void, PLUGIN_TYPE*> PluginRunFunction;
00050
00052 typedef boost::function1<boost::uint64_t, const PLUGIN_TYPE*> PluginStatFunction;
00053
00054
00056 PluginManager(void) {}
00057
00059 virtual ~PluginManager() {}
00060
00062 inline void clear(void) {
00063 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00064 m_plugin_map.clear();
00065 }
00066
00068 inline bool empty(void) const {
00069 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00070 return m_plugin_map.empty();
00071 }
00072
00079 inline void add(const std::string& plugin_id, PLUGIN_TYPE *plugin_object_ptr);
00080
00086 inline void remove(const std::string& plugin_id);
00087
00094 inline void replace(const std::string& plugin_id, PLUGIN_TYPE *plugin_ptr);
00095
00102 inline PLUGIN_TYPE *clone(const std::string& plugin_id);
00103
00112 inline PLUGIN_TYPE *load(const std::string& plugin_id, const std::string& plugin_type);
00113
00120 inline PLUGIN_TYPE *get(const std::string& plugin_id);
00121
00128 inline const PLUGIN_TYPE *get(const std::string& plugin_id) const;
00129
00136 inline PionPluginPtr<PLUGIN_TYPE> getLibPtr(const std::string& plugin_id) const;
00137
00144 inline PLUGIN_TYPE *find(const std::string& resource);
00145
00151 inline void run(PluginRunFunction run_func);
00152
00159 inline void run(const std::string& plugin_id, PluginRunFunction run_func);
00160
00166 inline boost::uint64_t getStatistic(PluginStatFunction stat_func) const;
00167
00174 inline boost::uint64_t getStatistic(const std::string& plugin_id,
00175 PluginStatFunction stat_func) const;
00176
00177
00178 protected:
00179
00181 class PluginMap
00182 : public std::map<std::string, std::pair<PLUGIN_TYPE *, PionPluginPtr<PLUGIN_TYPE> > >
00183 {
00184 public:
00185 inline void clear(void);
00186 virtual ~PluginMap() { PluginMap::clear(); }
00187 PluginMap(void) {}
00188 };
00189
00191 PluginMap m_plugin_map;
00192
00194 mutable boost::mutex m_plugin_mutex;
00195 };
00196
00197
00198
00199
00200 template <typename PLUGIN_TYPE>
00201 inline void PluginManager<PLUGIN_TYPE>::add(const std::string& plugin_id,
00202 PLUGIN_TYPE *plugin_object_ptr)
00203 {
00204 PionPluginPtr<PLUGIN_TYPE> plugin_ptr;
00205 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00206 m_plugin_map.insert(std::make_pair(plugin_id,
00207 std::make_pair(plugin_object_ptr, plugin_ptr)));
00208 }
00209
00210 template <typename PLUGIN_TYPE>
00211 inline void PluginManager<PLUGIN_TYPE>::remove(const std::string& plugin_id)
00212 {
00213 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00214 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i = m_plugin_map.find(plugin_id);
00215 if (i == m_plugin_map.end())
00216 throw PluginNotFoundException(plugin_id);
00217 if (i->second.second.is_open()) {
00218 i->second.second.destroy(i->second.first);
00219 } else {
00220 delete i->second.first;
00221 }
00222 m_plugin_map.erase(i);
00223 }
00224
00225 template <typename PLUGIN_TYPE>
00226 inline void PluginManager<PLUGIN_TYPE>::replace(const std::string& plugin_id, PLUGIN_TYPE *plugin_ptr)
00227 {
00228 PION_ASSERT(plugin_ptr);
00229 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00230 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i = m_plugin_map.find(plugin_id);
00231 if (i == m_plugin_map.end())
00232 throw PluginNotFoundException(plugin_id);
00233 if (i->second.second.is_open()) {
00234 i->second.second.destroy(i->second.first);
00235 } else {
00236 delete i->second.first;
00237 }
00238 i->second.first = plugin_ptr;
00239 }
00240
00241 template <typename PLUGIN_TYPE>
00242 inline PLUGIN_TYPE *PluginManager<PLUGIN_TYPE>::clone(const std::string& plugin_id)
00243 {
00244 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00245 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i = m_plugin_map.find(plugin_id);
00246 if (i == m_plugin_map.end())
00247 throw PluginNotFoundException(plugin_id);
00248 return i->second.second.create();
00249 }
00250
00251 template <typename PLUGIN_TYPE>
00252 inline PLUGIN_TYPE *PluginManager<PLUGIN_TYPE>::load(const std::string& plugin_id,
00253 const std::string& plugin_type)
00254 {
00255
00256 bool is_static;
00257 void *create_func;
00258 void *destroy_func;
00259
00260 if (m_plugin_map.find(plugin_id) != m_plugin_map.end())
00261 throw DuplicatePluginException(plugin_id);
00262
00263
00264 is_static = PionPlugin::findStaticEntryPoint(plugin_type, &create_func, &destroy_func);
00265
00266
00267 PionPluginPtr<PLUGIN_TYPE> plugin_ptr;
00268 if (is_static) {
00269 plugin_ptr.openStaticLinked(plugin_type, create_func, destroy_func);
00270 } else {
00271 plugin_ptr.open(plugin_type);
00272 }
00273
00274
00275 PLUGIN_TYPE *plugin_object_ptr(plugin_ptr.create());
00276
00277
00278 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00279 m_plugin_map.insert(std::make_pair(plugin_id,
00280 std::make_pair(plugin_object_ptr, plugin_ptr)));
00281
00282 return plugin_object_ptr;
00283 }
00284
00285 template <typename PLUGIN_TYPE>
00286 inline PLUGIN_TYPE *PluginManager<PLUGIN_TYPE>::get(const std::string& plugin_id)
00287 {
00288 PLUGIN_TYPE *plugin_object_ptr = NULL;
00289 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00290 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i = m_plugin_map.find(plugin_id);
00291 if (i != m_plugin_map.end())
00292 plugin_object_ptr = i->second.first;
00293 return plugin_object_ptr;
00294 }
00295
00296 template <typename PLUGIN_TYPE>
00297 inline const PLUGIN_TYPE *PluginManager<PLUGIN_TYPE>::get(const std::string& plugin_id) const
00298 {
00299 const PLUGIN_TYPE *plugin_object_ptr = NULL;
00300 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00301 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::const_iterator i = m_plugin_map.find(plugin_id);
00302 if (i != m_plugin_map.end())
00303 plugin_object_ptr = i->second.first;
00304 return plugin_object_ptr;
00305 }
00306
00307 template <typename PLUGIN_TYPE>
00308 inline PionPluginPtr<PLUGIN_TYPE> PluginManager<PLUGIN_TYPE>::getLibPtr(const std::string& plugin_id) const
00309 {
00310 PionPluginPtr<PLUGIN_TYPE> plugin_ptr;
00311 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00312 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::const_iterator i = m_plugin_map.find(plugin_id);
00313 if (i != m_plugin_map.end())
00314 plugin_ptr = i->second.second;
00315 return plugin_ptr;
00316 }
00317
00318 template <typename PLUGIN_TYPE>
00319 inline PLUGIN_TYPE *PluginManager<PLUGIN_TYPE>::find(const std::string& resource)
00320 {
00321
00322 PLUGIN_TYPE *plugin_object_ptr = NULL;
00323
00324
00325 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00326
00327
00328 if (m_plugin_map.empty()) return plugin_object_ptr;
00329
00330
00331 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i = m_plugin_map.upper_bound(resource);
00332 while (i != m_plugin_map.begin()) {
00333 --i;
00334
00335
00336 if (resource.compare(0, i->first.size(), i->first) != 0) {
00337
00338 if (i != m_plugin_map.begin()) {
00339
00340 typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator j=i;
00341 --j;
00342 if (j->first.size() < i->first.size())
00343 continue;
00344 }
00345
00346 break;
00347 }
00348
00349
00350
00351 if (resource.size() == i->first.size() || resource[i->first.size()]=='/') {
00352 plugin_object_ptr = i->second.first;
00353 break;
00354 }
00355 }
00356
00357 return plugin_object_ptr;
00358 }
00359
00360 template <typename PLUGIN_TYPE>
00361 inline void PluginManager<PLUGIN_TYPE>::run(PluginRunFunction run_func)
00362 {
00363 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00364 for (typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i = m_plugin_map.begin();
00365 i != m_plugin_map.end(); ++i)
00366 {
00367 run_func(i->second.first);
00368 }
00369 }
00370
00371 template <typename PLUGIN_TYPE>
00372 inline void PluginManager<PLUGIN_TYPE>::run(const std::string& plugin_id,
00373 PluginRunFunction run_func)
00374 {
00375
00376 PLUGIN_TYPE *plugin_object_ptr = get(plugin_id);
00377 if (plugin_object_ptr == NULL)
00378 throw PluginNotFoundException(plugin_id);
00379 run_func(plugin_object_ptr);
00380 }
00381
00382 template <typename PLUGIN_TYPE>
00383 inline boost::uint64_t PluginManager<PLUGIN_TYPE>::getStatistic(PluginStatFunction stat_func) const
00384 {
00385 boost::uint64_t stat_value = 0;
00386 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00387 for (typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::const_iterator i = m_plugin_map.begin();
00388 i != m_plugin_map.end(); ++i)
00389 {
00390 stat_value += stat_func(i->second.first);
00391 }
00392 return stat_value;
00393 }
00394
00395 template <typename PLUGIN_TYPE>
00396 inline boost::uint64_t PluginManager<PLUGIN_TYPE>::getStatistic(const std::string& plugin_id,
00397 PluginStatFunction stat_func) const
00398 {
00399
00400 const PLUGIN_TYPE *plugin_object_ptr = const_cast<PluginManager<PLUGIN_TYPE>*>(this)->get(plugin_id);
00401 if (plugin_object_ptr == NULL)
00402 throw PluginNotFoundException(plugin_id);
00403 return stat_func(plugin_object_ptr);
00404 }
00405
00406
00407
00408
00409 template <typename PLUGIN_TYPE>
00410 inline void PluginManager<PLUGIN_TYPE>::PluginMap::clear(void)
00411 {
00412 if (! empty()) {
00413 for (typename pion::PluginManager<PLUGIN_TYPE>::PluginMap::iterator i =
00414 std::map<std::string, std::pair<PLUGIN_TYPE *, PionPluginPtr<PLUGIN_TYPE> > >::begin();
00415 i != std::map<std::string, std::pair<PLUGIN_TYPE *, PionPluginPtr<PLUGIN_TYPE> > >::end(); ++i)
00416 {
00417 if (i->second.second.is_open()) {
00418 i->second.second.destroy(i->second.first);
00419 } else {
00420 delete i->second.first;
00421 }
00422 }
00423 erase(std::map<std::string, std::pair<PLUGIN_TYPE *, PionPluginPtr<PLUGIN_TYPE> > >::begin(),
00424 std::map<std::string, std::pair<PLUGIN_TYPE *, PionPluginPtr<PLUGIN_TYPE> > >::end());
00425 }
00426 }
00427
00428
00429 }
00430
00431 #endif