00001 #ifndef _sys_Module_h
00002 #define _sys_Module_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <boost/noncopyable.hpp>
00025 #include <iostream>
00026 #include "qpid/QpidError.h"
00027
00028 namespace qpid {
00029 namespace sys {
00030 #if USE_APR
00031 #include <apr_dso.h>
00032 typedef apr_dso_handle_t* dso_handle_t;
00033 #else
00034 typedef void* dso_handle_t;
00035 #endif
00036
00037 template <class T> class Module : private boost::noncopyable
00038 {
00039 typedef T* create_t();
00040 typedef void destroy_t(T*);
00041
00042 dso_handle_t handle;
00043 destroy_t* destroy;
00044 T* ptr;
00045
00046 void load(const std::string& name);
00047 void unload();
00048 void* getSymbol(const std::string& name);
00049
00050 public:
00051 Module(const std::string& name);
00052 T* operator->();
00053 T* get();
00054 ~Module() throw();
00055 };
00056
00057 }
00058 }
00059
00060 using namespace qpid::sys;
00061
00062 template <class T> Module<T>::Module(const std::string& module) : destroy(0), ptr(0)
00063 {
00064 load(module);
00065
00066
00067
00068
00069 create_t* create = reinterpret_cast<create_t*>(reinterpret_cast<intptr_t>(getSymbol("create")));
00070 destroy = reinterpret_cast<destroy_t*>(reinterpret_cast<intptr_t>(getSymbol("destroy")));
00071 ptr = create();
00072 }
00073
00074 template <class T> T* Module<T>::operator->()
00075 {
00076 return ptr;
00077 }
00078
00079 template <class T> T* Module<T>::get()
00080 {
00081 return ptr;
00082 }
00083
00084 template <class T> Module<T>::~Module() throw()
00085 {
00086 try {
00087 if (handle && ptr) {
00088 destroy(ptr);
00089 }
00090 if (handle) unload();
00091 } catch (std::exception& e) {
00092 std::cout << "Error while destroying module: " << e.what() << std::endl;
00093 }
00094 destroy = 0;
00095 handle = 0;
00096 ptr = 0;
00097 }
00098
00099
00100 #if USE_APR
00101
00102 #include "apr/APRBase.h"
00103 #include "apr/APRPool.h"
00104
00105 template <class T> void Module<T>::load(const std::string& name)
00106 {
00107 CHECK_APR_SUCCESS(apr_dso_load(&handle, name.c_str(), APRPool::get()));
00108 }
00109
00110 template <class T> void Module<T>::unload()
00111 {
00112 CHECK_APR_SUCCESS(apr_dso_unload(handle));
00113 }
00114
00115 template <class T> void* Module<T>::getSymbol(const std::string& name)
00116 {
00117 apr_dso_handle_sym_t symbol;
00118 CHECK_APR_SUCCESS(apr_dso_sym(&symbol, handle, name.c_str()));
00119 return (void*) symbol;
00120 }
00121
00122
00123 #else
00124
00125 #include <dlfcn.h>
00126
00127 template <class T> void Module<T>::load(const std::string& name)
00128 {
00129 dlerror();
00130 handle = dlopen(name.c_str(), RTLD_NOW);
00131 const char* error = dlerror();
00132 if (error) {
00133 THROW_QPID_ERROR(INTERNAL_ERROR, error);
00134 }
00135 }
00136
00137 template <class T> void Module<T>::unload()
00138 {
00139 dlerror();
00140 dlclose(handle);
00141 const char* error = dlerror();
00142 if (error) {
00143 THROW_QPID_ERROR(INTERNAL_ERROR, error);
00144 }
00145 }
00146
00147 template <class T> void* Module<T>::getSymbol(const std::string& name)
00148 {
00149 dlerror();
00150 void* sym = dlsym(handle, name.c_str());
00151 const char* error = dlerror();
00152 if (error) {
00153 THROW_QPID_ERROR(INTERNAL_ERROR, error);
00154 }
00155 return sym;
00156 }
00157
00158 #endif //if USE_APR
00159
00160 #endif //ifndef _sys_Module_h
00161