00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __PION_PLUGIN_MANAGER_HEADER__
00011 #define __PION_PLUGIN_MANAGER_HEADER__
00012
00013 #include <map>
00014 #include <string>
00015 #include <boost/cstdint.hpp>
00016 #include <boost/assert.hpp>
00017 #include <boost/function.hpp>
00018 #include <boost/function/function1.hpp>
00019 #include <boost/thread/mutex.hpp>
00020 #include <pion/config.hpp>
00021 #include <pion/error.hpp>
00022 #include <pion/plugin.hpp>
00023
00024
00025 namespace pion {
00026
00030 template <typename PluginType>
00031 class plugin_manager
00032 {
00033 public:
00034
00036 typedef boost::function1<void, PluginType*> PluginRunFunction;
00037
00039 typedef boost::function1<boost::uint64_t, const PluginType*> PluginStatFunction;
00040
00041
00043 plugin_manager(void) {}
00044
00046 virtual ~plugin_manager() {}
00047
00049 inline void clear(void) {
00050 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00051 m_plugin_map.clear();
00052 }
00053
00055 inline bool empty(void) const {
00056 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00057 return m_plugin_map.empty();
00058 }
00059
00066 inline void add(const std::string& plugin_id, PluginType *plugin_object_ptr);
00067
00073 inline void remove(const std::string& plugin_id);
00074
00081 inline void replace(const std::string& plugin_id, PluginType *plugin_ptr);
00082
00089 inline PluginType *clone(const std::string& plugin_id);
00090
00099 inline PluginType *load(const std::string& plugin_id, const std::string& plugin_type);
00100
00107 inline PluginType *get(const std::string& plugin_id);
00108
00115 inline const PluginType *get(const std::string& plugin_id) const;
00116
00123 inline plugin_ptr<PluginType> get_lib_ptr(const std::string& plugin_id) const;
00124
00131 inline PluginType *find(const std::string& resource);
00132
00138 inline void run(PluginRunFunction run_func);
00139
00146 inline void run(const std::string& plugin_id, PluginRunFunction run_func);
00147
00153 inline boost::uint64_t get_statistic(PluginStatFunction stat_func) const;
00154
00161 inline boost::uint64_t get_statistic(const std::string& plugin_id,
00162 PluginStatFunction stat_func) const;
00163
00164
00165 protected:
00166
00168 class map_type
00169 : public std::map<std::string, std::pair<PluginType *, plugin_ptr<PluginType> > >
00170 {
00171 public:
00172 inline void clear(void);
00173 virtual ~map_type() { map_type::clear(); }
00174 map_type(void) {}
00175 };
00176
00178 map_type m_plugin_map;
00179
00181 mutable boost::mutex m_plugin_mutex;
00182 };
00183
00184
00185
00186
00187 template <typename PluginType>
00188 inline void plugin_manager<PluginType>::add(const std::string& plugin_id,
00189 PluginType *plugin_object_ptr)
00190 {
00191 plugin_ptr<PluginType> plugin_ptr;
00192 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00193 m_plugin_map.insert(std::make_pair(plugin_id,
00194 std::make_pair(plugin_object_ptr, plugin_ptr)));
00195 }
00196
00197 template <typename PluginType>
00198 inline void plugin_manager<PluginType>::remove(const std::string& plugin_id)
00199 {
00200 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00201 typename pion::plugin_manager<PluginType>::map_type::iterator i = m_plugin_map.find(plugin_id);
00202 if (i == m_plugin_map.end())
00203 BOOST_THROW_EXCEPTION( error::plugin_not_found() << error::errinfo_plugin_name(plugin_id) );
00204 if (i->second.second.is_open()) {
00205 i->second.second.destroy(i->second.first);
00206 } else {
00207 delete i->second.first;
00208 }
00209 m_plugin_map.erase(i);
00210 }
00211
00212 template <typename PluginType>
00213 inline void plugin_manager<PluginType>::replace(const std::string& plugin_id, PluginType *plugin_ptr)
00214 {
00215 BOOST_ASSERT(plugin_ptr);
00216 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00217 typename pion::plugin_manager<PluginType>::map_type::iterator i = m_plugin_map.find(plugin_id);
00218 if (i == m_plugin_map.end())
00219 BOOST_THROW_EXCEPTION( error::plugin_not_found() << error::errinfo_plugin_name(plugin_id) );
00220 if (i->second.second.is_open()) {
00221 i->second.second.destroy(i->second.first);
00222 } else {
00223 delete i->second.first;
00224 }
00225 i->second.first = plugin_ptr;
00226 }
00227
00228 template <typename PluginType>
00229 inline PluginType *plugin_manager<PluginType>::clone(const std::string& plugin_id)
00230 {
00231 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00232 typename pion::plugin_manager<PluginType>::map_type::iterator i = m_plugin_map.find(plugin_id);
00233 if (i == m_plugin_map.end())
00234 BOOST_THROW_EXCEPTION( error::plugin_not_found() << error::errinfo_plugin_name(plugin_id) );
00235 return i->second.second.create();
00236 }
00237
00238 template <typename PluginType>
00239 inline PluginType *plugin_manager<PluginType>::load(const std::string& plugin_id,
00240 const std::string& plugin_type)
00241 {
00242
00243 if (m_plugin_map.find(plugin_id) != m_plugin_map.end())
00244 BOOST_THROW_EXCEPTION( error::duplicate_plugin() << error::errinfo_plugin_name(plugin_id) );
00245
00246
00247 plugin_ptr<PluginType> plugin_ptr;
00248 plugin_ptr.open(plugin_type);
00249
00250
00251 PluginType *plugin_object_ptr(plugin_ptr.create());
00252
00253
00254 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00255 m_plugin_map.insert(std::make_pair(plugin_id,
00256 std::make_pair(plugin_object_ptr, plugin_ptr)));
00257
00258 return plugin_object_ptr;
00259 }
00260
00261 template <typename PluginType>
00262 inline PluginType *plugin_manager<PluginType>::get(const std::string& plugin_id)
00263 {
00264 PluginType *plugin_object_ptr = NULL;
00265 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00266 typename pion::plugin_manager<PluginType>::map_type::iterator i = m_plugin_map.find(plugin_id);
00267 if (i != m_plugin_map.end())
00268 plugin_object_ptr = i->second.first;
00269 return plugin_object_ptr;
00270 }
00271
00272 template <typename PluginType>
00273 inline const PluginType *plugin_manager<PluginType>::get(const std::string& plugin_id) const
00274 {
00275 const PluginType *plugin_object_ptr = NULL;
00276 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00277 typename pion::plugin_manager<PluginType>::map_type::const_iterator i = m_plugin_map.find(plugin_id);
00278 if (i != m_plugin_map.end())
00279 plugin_object_ptr = i->second.first;
00280 return plugin_object_ptr;
00281 }
00282
00283 template <typename PluginType>
00284 inline plugin_ptr<PluginType> plugin_manager<PluginType>::get_lib_ptr(const std::string& plugin_id) const
00285 {
00286 plugin_ptr<PluginType> plugin_ptr;
00287 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00288 typename pion::plugin_manager<PluginType>::map_type::const_iterator i = m_plugin_map.find(plugin_id);
00289 if (i != m_plugin_map.end())
00290 plugin_ptr = i->second.second;
00291 return plugin_ptr;
00292 }
00293
00294 template <typename PluginType>
00295 inline PluginType *plugin_manager<PluginType>::find(const std::string& resource)
00296 {
00297
00298 PluginType *plugin_object_ptr = NULL;
00299
00300
00301 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00302
00303
00304 if (m_plugin_map.empty()) return plugin_object_ptr;
00305
00306
00307 typename pion::plugin_manager<PluginType>::map_type::iterator i = m_plugin_map.upper_bound(resource);
00308 while (i != m_plugin_map.begin()) {
00309 --i;
00310
00311
00312 if (resource.compare(0, i->first.size(), i->first) != 0) {
00313
00314 if (i != m_plugin_map.begin()) {
00315
00316 typename pion::plugin_manager<PluginType>::map_type::iterator j=i;
00317 --j;
00318 if (j->first.size() < i->first.size())
00319 continue;
00320 }
00321
00322 break;
00323 }
00324
00325
00326
00327 if (resource.size() == i->first.size() || resource[i->first.size()]=='/') {
00328 plugin_object_ptr = i->second.first;
00329 break;
00330 }
00331 }
00332
00333 return plugin_object_ptr;
00334 }
00335
00336 template <typename PluginType>
00337 inline void plugin_manager<PluginType>::run(PluginRunFunction run_func)
00338 {
00339 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00340 for (typename pion::plugin_manager<PluginType>::map_type::iterator i = m_plugin_map.begin();
00341 i != m_plugin_map.end(); ++i)
00342 {
00343 run_func(i->second.first);
00344 }
00345 }
00346
00347 template <typename PluginType>
00348 inline void plugin_manager<PluginType>::run(const std::string& plugin_id,
00349 PluginRunFunction run_func)
00350 {
00351
00352 PluginType *plugin_object_ptr = get(plugin_id);
00353 if (plugin_object_ptr == NULL)
00354 BOOST_THROW_EXCEPTION( error::plugin_not_found() << error::errinfo_plugin_name(plugin_id) );
00355 run_func(plugin_object_ptr);
00356 }
00357
00358 template <typename PluginType>
00359 inline boost::uint64_t plugin_manager<PluginType>::get_statistic(PluginStatFunction stat_func) const
00360 {
00361 boost::uint64_t stat_value = 0;
00362 boost::mutex::scoped_lock plugins_lock(m_plugin_mutex);
00363 for (typename pion::plugin_manager<PluginType>::map_type::const_iterator i = m_plugin_map.begin();
00364 i != m_plugin_map.end(); ++i)
00365 {
00366 stat_value += stat_func(i->second.first);
00367 }
00368 return stat_value;
00369 }
00370
00371 template <typename PluginType>
00372 inline boost::uint64_t plugin_manager<PluginType>::get_statistic(const std::string& plugin_id,
00373 PluginStatFunction stat_func) const
00374 {
00375
00376 const PluginType *plugin_object_ptr = const_cast<plugin_manager<PluginType>*>(this)->get(plugin_id);
00377 if (plugin_object_ptr == NULL)
00378 BOOST_THROW_EXCEPTION( error::plugin_not_found() << error::errinfo_plugin_name(plugin_id) );
00379 return stat_func(plugin_object_ptr);
00380 }
00381
00382
00383
00384
00385 template <typename PluginType>
00386 inline void plugin_manager<PluginType>::map_type::clear(void)
00387 {
00388 if (! std::map<std::string, std::pair<PluginType *, plugin_ptr<PluginType> > >::empty()) {
00389 for (typename pion::plugin_manager<PluginType>::map_type::iterator i =
00390 std::map<std::string, std::pair<PluginType *, plugin_ptr<PluginType> > >::begin();
00391 i != std::map<std::string, std::pair<PluginType *, plugin_ptr<PluginType> > >::end(); ++i)
00392 {
00393 if (i->second.second.is_open()) {
00394 i->second.second.destroy(i->second.first);
00395 } else {
00396 delete i->second.first;
00397 }
00398 }
00399 this->erase(std::map<std::string, std::pair<PluginType *, plugin_ptr<PluginType> > >::begin(),
00400 std::map<std::string, std::pair<PluginType *, plugin_ptr<PluginType> > >::end());
00401 }
00402 }
00403
00404
00405 }
00406
00407 #endif