~cemil-azizoglu/mir/improve-raii-take2

« back to all changes in this revision

Viewing changes to include/common/mir/module_deleter.h

  • Committer: Cemil Azizoglu
  • Date: 2015-02-26 23:37:35 UTC
  • mfrom: (2323.1.24 development-branch)
  • Revision ID: cemil.azizoglu@canonical.com-20150226233735-zm2j3eunf26b2hgb
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2015 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License version 3,
 
6
 * as published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
 
17
 */
 
18
 
 
19
#ifndef MIR_MODULE_DELETER_H_
 
20
#define MIR_MODULE_DELETER_H_
 
21
 
 
22
#include <memory>
 
23
 
 
24
namespace mir
 
25
{
 
26
class SharedLibrary;
 
27
 
 
28
namespace detail
 
29
{
 
30
class RefCountedLibrary
 
31
{
 
32
public:
 
33
    RefCountedLibrary(void* adrress);
 
34
    RefCountedLibrary(RefCountedLibrary const&);
 
35
    ~RefCountedLibrary();
 
36
    RefCountedLibrary& operator=(RefCountedLibrary const&);
 
37
private:
 
38
    std::shared_ptr<mir::SharedLibrary> internal_state;
 
39
};
 
40
}
 
41
 
 
42
namespace
 
43
{
 
44
template<typename T>
 
45
struct ModuleDeleter;
 
46
}
 
47
 
 
48
/*!
 
49
 * \brief Use UniqueModulePtr to ensure that your loadable libray outlives
 
50
 * instances created within it.
 
51
 *
 
52
 * Use mir::make_module_ptr(...) or pass a function from your library to the
 
53
 * constructor, to increase the lifetime of your library:
 
54
 * \code
 
55
 *  mir::UniqueModulePtr<ExampleInterface> library_entry_point()
 
56
 *  {
 
57
 *      return mir::UniqueModulePtr<SomeInterface>(new Implementation, &library_entry_point);
 
58
 *  }
 
59
 * \endcode
 
60
 *
 
61
 * The default constructor will not try to infer the dynamic library.
 
62
 */
 
63
template<typename T>
 
64
using UniqueModulePtr = std::unique_ptr<T,ModuleDeleter<T>>;
 
65
 
 
66
namespace
 
67
{
 
68
/*!
 
69
 * \brief make_unique like creation function for UniqueModulePtr
 
70
 */
 
71
template<typename Type, typename... Args>
 
72
inline auto make_module_ptr(Args&&... args)
 
73
-> UniqueModulePtr<Type>
 
74
{
 
75
    return UniqueModulePtr<Type>(new Type(std::forward<Args>(args)...), &make_module_ptr<Type, Args...>);
 
76
}
 
77
 
 
78
template<typename T>
 
79
struct ModuleDeleter : std::default_delete<T>
 
80
{
 
81
    ModuleDeleter() : library(nullptr) {}
 
82
    template<typename U>
 
83
    ModuleDeleter(ModuleDeleter<U> const& other)
 
84
        : std::default_delete<T>{other},
 
85
        library{other.get_library()}
 
86
    {
 
87
    }
 
88
 
 
89
    detail::RefCountedLibrary get_library() const
 
90
    {
 
91
        return library;
 
92
    }
 
93
private:
 
94
    template<typename R, typename... Rs>
 
95
    ModuleDeleter(R (*function)(Rs...))
 
96
        : library{reinterpret_cast<void*>(function)}
 
97
    {
 
98
    }
 
99
 
 
100
    detail::RefCountedLibrary library;
 
101
    template<typename Type, typename... Args>
 
102
    friend std::unique_ptr<Type, ModuleDeleter<Type>> make_module_ptr(Args&&... args);
 
103
};
 
104
}
 
105
 
 
106
}
 
107
 
 
108
#endif
 
109