/home/aconway/svn/qpid/cpp/src/qpid/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 "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     //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     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 // POSIX================================================================
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 

Generated on Tue Apr 17 14:22:03 2007 for Qpid by  doxygen 1.4.7