summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/sys/apr/Module.h
blob: d77cc0f3883a6bc0de770a5b9e643d08f2b95b46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#ifndef _sys_apr_Module_h
#define _sys_apr_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 "qpid/QpidError.h"
#include "APRBase.h"
#include "APRPool.h"

#include <boost/noncopyable.hpp>
#include <iostream>
#include <apr_dso.h>

namespace qpid {
namespace sys {

typedef apr_dso_handle_t* dso_handle_t;

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();
};

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;
}

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;
}

}}
#endif //ifndef _sys_apr_Module_h