/opt/workspace/qpid/tags/M2/Final/cpp/lib/common/sys/Module.h

00001 #ifndef _sys_Module_h
00002 #define _sys_Module_h
00003 
00004 /*
00005  *
00006  * Licensed to the Apache Software Foundation (ASF) under one
00007  * or more contributor license agreements.  See the NOTICE file
00008  * distributed with this work for additional information
00009  * regarding copyright ownership.  The ASF licenses this file
00010  * to you under the Apache License, Version 2.0 (the
00011  * "License"); you may not use this file except in compliance
00012  * with the License.  You may obtain a copy of the License at
00013  * 
00014  *   http://www.apache.org/licenses/LICENSE-2.0
00015  * 
00016  * Unless required by applicable law or agreed to in writing,
00017  * software distributed under the License is distributed on an
00018  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00019  * KIND, either express or implied.  See the License for the
00020  * specific language governing permissions and limitations
00021  * under the License.
00022  *
00023  */
00024 #include <boost/noncopyable.hpp>
00025 #include <iostream>
00026 #include <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     //TODO: need a better strategy for symbol names to allow multiple
00066     //modules to be loaded without clashes...
00067 
00068     //Note: need the double cast to avoid errors in casting from void* to function pointer with -pedantic
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 // APR ================================================================
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     apr_pool_t* pool = APRPool::get();
00108     CHECK_APR_SUCCESS(apr_dso_load(&handle, name.c_str(), pool));
00109     APRPool::free(pool);
00110 }
00111 
00112 template <class T> void Module<T>::unload()
00113 {
00114     CHECK_APR_SUCCESS(apr_dso_unload(handle));
00115 }
00116 
00117 template <class T> void* Module<T>::getSymbol(const std::string& name)
00118 {
00119     apr_dso_handle_sym_t symbol;
00120     CHECK_APR_SUCCESS(apr_dso_sym(&symbol, handle, name.c_str()));
00121     return (void*) symbol;
00122 }
00123 
00124 // POSIX================================================================
00125 #else 
00126 
00127 #include <dlfcn.h>
00128 
00129 template <class T> void Module<T>::load(const std::string& name)
00130 {
00131     dlerror();
00132     handle = dlopen(name.c_str(), RTLD_NOW);
00133     const char* error = dlerror();
00134     if (error) {
00135         THROW_QPID_ERROR(INTERNAL_ERROR, error);
00136     }
00137 }
00138 
00139 template <class T> void Module<T>::unload()
00140 {
00141     dlerror();
00142     dlclose(handle);
00143     const char* error = dlerror();
00144     if (error) {
00145         THROW_QPID_ERROR(INTERNAL_ERROR, error);
00146     }
00147 }
00148 
00149 template <class T> void* Module<T>::getSymbol(const std::string& name)
00150 {
00151     dlerror();
00152     void* sym = dlsym(handle, name.c_str());
00153     const char* error = dlerror();
00154     if (error) {
00155         THROW_QPID_ERROR(INTERNAL_ERROR, error);
00156     }
00157     return sym;
00158 }
00159 
00160 #endif //if USE_APR
00161 
00162 #endif //ifndef _sys_Module_h
00163 

Generated on Mon Nov 26 19:13:17 2007 for Qpid by  doxygen 1.5.1