- Main Page
- Classes
- Files

- File List

# include/pion/plugin.hpp

    00001 // ---------------------------------------------------------------------
    00002 // pion:  a Boost C++ framework for building lightweight HTTP interfaces
    00003 // ---------------------------------------------------------------------
    00004 // Copyright (C) 2007-2012 Cloudmeter, Inc.  (http://www.cloudmeter.com)
    00005 //
    00006 // Distributed under the Boost Software License, Version 1.0.
    00007 // See http://www.boost.org/LICENSE_1_0.txt
    00008 //
    00009
    00010 #ifndef __PION_PLUGIN_HEADER__
    00011 #define __PION_PLUGIN_HEADER__
    00012
    00013 #include <vector>
    00014 #include <string>
    00015 #include <map>
    00016 #include <list>
    00017 #include <boost/noncopyable.hpp>
    00018 #include <boost/thread/once.hpp>
    00019 #include <boost/thread/mutex.hpp>
    00020 #include <boost/filesystem/path.hpp>
    00021 #include <pion/config.hpp>
    00022 #include <pion/error.hpp>
    00023
    00024
    00025 namespace pion {    // begin namespace pion
    00026
    00030 class PION_API plugin {
    00031 public:
    00032
    00040     static inline bool find_plugin_file(std::string& path_to_file,
    00041                                       const std::string& name)
    00042     {
    00043         return find_file(path_to_file, name, PION_PLUGIN_EXTENSION);
    00044     }
    00045
    00053     static inline bool find_config_file(std::string& path_to_file,
    00054                                       const std::string& name)
    00055     {
    00056         return find_file(path_to_file, name, PION_CONFIG_EXTENSION);
    00057     }
    00058
    00067     static void add_static_entry_point(const std::string& plugin_name,
    00068                                     void *create_func,
    00069                                     void *destroy_func);
    00070
    00079     static void check_cygwin_path(boost::filesystem::path& final_path,
    00080                                 const std::string& path_string);
    00081
    00083     static void add_plugin_directory(const std::string& dir);
    00084
    00086     static void reset_plugin_directories(void);
    00087
    00088
    00089     // default destructor
    00090     virtual ~plugin() { release_data(); }
    00091
    00093     inline bool is_open(void) const { return (m_plugin_data != NULL); }
    00094
    00096     inline std::string get_plugin_name(void) const {
    00097         return (is_open() ? m_plugin_data->m_plugin_name : std::string());
    00098     }
    00099
    00101     static void get_all_plugin_names(std::vector<std::string>& plugin_names);
    00102
    00115     void open(const std::string& plugin_name);
    00116
    00129     void open_file(const std::string& plugin_file);
    00130
    00132     inline void close(void) { release_data(); }
    00133
    00134 protected:
    00135
    00139     struct data_type
    00140     {
    00142         data_type(void)
    00143             : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
    00144             m_references(0)
    00145         {}
    00146         data_type(const std::string& plugin_name)
    00147             : m_lib_handle(NULL), m_create_func(NULL), m_destroy_func(NULL),
    00148             m_plugin_name(plugin_name), m_references(0)
    00149         {}
    00150         data_type(const data_type& p)
    00151             : m_lib_handle(p.m_lib_handle), m_create_func(p.m_create_func),
    00152             m_destroy_func(p.m_destroy_func), m_plugin_name(p.m_plugin_name),
    00153             m_references(p.m_references)
    00154         {}
    00155
    00157         void *          m_lib_handle;
    00158
    00160         void *          m_create_func;
    00161
    00163         void *          m_destroy_func;
    00164
    00166         std::string     m_plugin_name;
    00167
    00169         unsigned long   m_references;
    00170     };
    00171
    00172
    00174     plugin(void) : m_plugin_data(NULL) {}
    00175
    00177     plugin(const plugin& p) : m_plugin_data(NULL) { grab_data(p); }
    00178
    00180     plugin& operator=(const plugin& p) { grab_data(p); return *this; }
    00181
    00183     inline void *get_create_function(void) {
    00184         return (is_open() ? m_plugin_data->m_create_func : NULL);
    00185     }
    00186
    00188     inline void *get_destroy_function(void) {
    00189         return (is_open() ? m_plugin_data->m_destroy_func : NULL);
    00190     }
    00191
    00193     void release_data(void);
    00194
    00196     void grab_data(const plugin& p);
    00197
    00198
    00199 private:
    00200
    00202     typedef std::map<std::string, data_type*>  map_type;
    00203
    00205     struct config_type {
    00207         std::vector<std::string>    m_plugin_dirs;
    00208
    00210         map_type                    m_plugin_map;
    00211
    00213         boost::mutex                m_plugin_mutex;
    00214     };
    00215
    00216
    00218     static inline config_type& get_plugin_config(void) {
    00219         boost::call_once(plugin::create_plugin_config, m_instance_flag);
    00220         return *m_config_ptr;
    00221     }
    00222
    00224     static void create_plugin_config(void);
    00225
    00235     static bool find_file(std::string& path_to_file, const std::string& name,
    00236                          const std::string& extension);
    00237
    00248     static bool check_for_file(std::string& final_path, const std::string& start_path,
    00249                              const std::string& name, const std::string& extension);
    00250
    00257     static void open_plugin(const std::string& plugin_file,
    00258                            data_type& plugin_data);
    00259
    00261     static std::string get_plugin_name(const std::string& plugin_file);
    00262
    00264     static void *load_dynamic_library(const std::string& plugin_file);
    00265
    00267     static void close_dynamic_library(void *lib_handle);
    00268
    00270     static void *get_library_symbol(void *lib_handle, const std::string& symbol);
    00271
    00272
    00274     static const std::string            PION_PLUGIN_CREATE;
    00275
    00277     static const std::string            PION_PLUGIN_DESTROY;
    00278
    00280     static const std::string            PION_PLUGIN_EXTENSION;
    00281
    00283     static const std::string            PION_CONFIG_EXTENSION;
    00284
    00286     static boost::once_flag             m_instance_flag;
    00287
    00289     static config_type *           m_config_ptr;
    00290
    00292     data_type *                    m_plugin_data;
    00293 };
    00294
    00295
    00300 template <typename InterfaceClassType>
    00301 class plugin_ptr :
    00302     public plugin
    00303 {
    00304 protected:
    00305
    00307     typedef InterfaceClassType* CreateObjectFunction(void);
    00308
    00310     typedef void DestroyObjectFunction(InterfaceClassType*);
    00311
    00312
    00313 public:
    00314
    00316     plugin_ptr(void) : plugin() {}
    00317     virtual ~plugin_ptr() {}
    00318
    00320     plugin_ptr(const plugin_ptr& p) : plugin(p) {}
    00321
    00323     plugin_ptr& operator=(const plugin_ptr& p) { grab_data(p); return *this; }
    00324
    00326     inline InterfaceClassType *create(void) {
    00327         CreateObjectFunction *create_func =
    00328             (CreateObjectFunction*)(get_create_function());
    00329         if (create_func == NULL)
    00330             BOOST_THROW_EXCEPTION( error::plugin_undefined() );
    00331         return create_func();
    00332     }
    00333
    00335     inline void destroy(InterfaceClassType *object_ptr) {
    00336         // fix warning ISO C++ forbids casting from pointer-to-object
    00337         // to pointer to function
    00338         union {
    00339             void* v_;
    00340             DestroyObjectFunction* f_;
    00341         } Cast;
    00342         Cast.v_ = get_destroy_function();
    00343         DestroyObjectFunction *destroy_func = Cast.f_;
    00344         if (destroy_func == NULL)
    00345             BOOST_THROW_EXCEPTION( error::plugin_undefined() );
    00346         destroy_func(object_ptr);
    00347     }
    00348 };
    00349
    00350
    00354 template <typename InterfaceClassType>
    00355 class plugin_instance_ptr :
    00356     private boost::noncopyable
    00357 {
    00358 public:
    00359
    00361     plugin_instance_ptr(void) : m_instance_ptr(NULL) {}
    00362
    00364     virtual ~plugin_instance_ptr() { reset(); }
    00365
    00367     inline void reset(void) {
    00368         if (m_instance_ptr) {
    00369             m_plugin_ptr.destroy(m_instance_ptr);
    00370         }
    00371     }
    00372
    00374     inline void create(const std::string& plugin_type) {
    00375         reset();
    00376         m_plugin_ptr.open(plugin_type);
    00377         m_instance_ptr = m_plugin_ptr.create();
    00378     }
    00379
    00381     inline bool empty(void) const { return m_instance_ptr==NULL; }
    00382
    00384     inline InterfaceClassType *get(void) { return m_instance_ptr; }
    00385
    00387     inline InterfaceClassType& operator*(void) { return *m_instance_ptr; }
    00388
    00390     inline const InterfaceClassType& operator*(void) const { return *m_instance_ptr; }
    00391
    00393     inline InterfaceClassType* operator->(void) { return m_instance_ptr; }
    00394
    00396     inline const InterfaceClassType* operator->(void) const { return m_instance_ptr; }
    00397
    00398
    00399 protected:
    00400
    00402     plugin_ptr<InterfaceClassType>   m_plugin_ptr;
    00403
    00405     InterfaceClassType  *               m_instance_ptr;
    00406 };
    00407
    00408
    00422 #ifdef PION_STATIC_LINKING
    00423
    00424 #define PION_DECLARE_PLUGIN(plugin_name)    \
    00425     class plugin_name;                      \
    00426     extern "C" plugin_name *pion_create_##plugin_name(void); \
    00427     extern "C" void pion_destroy_##plugin_name(plugin_name *plugin_ptr); \
    00428     static pion::static_entry_point_helper helper_##plugin_name(#plugin_name, (void*) pion_create_##plugin_name, (void*) pion_destroy_##plugin_name);
    00429
    00431 class static_entry_point_helper {
    00432 public:
    00433     static_entry_point_helper(const std::string& name, void *create, void *destroy)
    00434     {
    00435         pion::plugin::add_static_entry_point(name, create, destroy);
    00436     }
    00437 };
    00438
    00439 #else
    00440
    00441 #define PION_DECLARE_PLUGIN(plugin_name)
    00442
    00443 #endif
    00444
    00445 }   // end namespace pion
    00446
    00447 #endif