blob: 9bf5d6e1fc95b77e690407dae6f4b701ec46c803 [file] [log] [blame]
#ifndef _sys_Module_h
#define _sys_Module_h
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
#include <boost/noncopyable.hpp>
#include <iostream>
#include <QpidError.h>
namespace qpid {
namespace sys {
#if USE_APR
#include <apr_dso.h>
typedef apr_dso_handle_t* dso_handle_t;
#else
typedef void* dso_handle_t;
#endif
template <class T> class Module : private boost::noncopyable
{
typedef T* create_t();
typedef void destroy_t(T*);
dso_handle_t handle;
destroy_t* destroy;
T* ptr;
void load(const std::string& name);
void unload();
void* getSymbol(const std::string& name);
public:
Module(const std::string& name);
T* operator->();
T* get();
~Module() throw();
};
}
}
using namespace qpid::sys;
template <class T> Module<T>::Module(const std::string& module) : destroy(0), ptr(0)
{
load(module);
//TODO: need a better strategy for symbol names to allow multiple
//modules to be loaded without clashes...
//Note: need the double cast to avoid errors in casting from void* to function pointer with -pedantic
create_t* create = reinterpret_cast<create_t*>(reinterpret_cast<intptr_t>(getSymbol("create")));
destroy = reinterpret_cast<destroy_t*>(reinterpret_cast<intptr_t>(getSymbol("destroy")));
ptr = create();
}
template <class T> T* Module<T>::operator->()
{
return ptr;
}
template <class T> T* Module<T>::get()
{
return ptr;
}
template <class T> Module<T>::~Module() throw()
{
try {
if (handle && ptr) {
destroy(ptr);
}
if (handle) unload();
} catch (std::exception& e) {
std::cout << "Error while destroying module: " << e.what() << std::endl;
}
destroy = 0;
handle = 0;
ptr = 0;
}
// APR ================================================================
#if USE_APR
#include <apr/APRBase.h>
#include <apr/APRPool.h>
template <class T> void Module<T>::load(const std::string& name)
{
CHECK_APR_SUCCESS(apr_dso_load(&handle, name.c_str(), APRPool::get()));
}
template <class T> void Module<T>::unload()
{
CHECK_APR_SUCCESS(apr_dso_unload(handle));
}
template <class T> void* Module<T>::getSymbol(const std::string& name)
{
apr_dso_handle_sym_t symbol;
CHECK_APR_SUCCESS(apr_dso_sym(&symbol, handle, name.c_str()));
return (void*) symbol;
}
// POSIX================================================================
#else
#include <dlfcn.h>
template <class T> void Module<T>::load(const std::string& name)
{
dlerror();
handle = dlopen(name.c_str(), RTLD_NOW);
const char* error = dlerror();
if (error) {
THROW_QPID_ERROR(INTERNAL_ERROR, error);
}
}
template <class T> void Module<T>::unload()
{
dlerror();
dlclose(handle);
const char* error = dlerror();
if (error) {
THROW_QPID_ERROR(INTERNAL_ERROR, error);
}
}
template <class T> void* Module<T>::getSymbol(const std::string& name)
{
dlerror();
void* sym = dlsym(handle, name.c_str());
const char* error = dlerror();
if (error) {
THROW_QPID_ERROR(INTERNAL_ERROR, error);
}
return sym;
}
#endif //if USE_APR
#endif //ifndef _sys_Module_h