Commit | Line | Data |
---|---|---|
8802d23b JG |
1 | /* |
2 | * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | */ | |
7 | ||
8 | #ifndef LTTNG_MAKE_UNIQUE_WRAPPER_H | |
9 | #define LTTNG_MAKE_UNIQUE_WRAPPER_H | |
10 | ||
11 | #include <common/macros.hpp> | |
12 | ||
13 | #include <memory> | |
14 | ||
15 | namespace lttng { | |
16 | ||
17 | /* | |
18 | * make_unique_wrapper is intended to facilitate the use of std::unique_ptr | |
19 | * to wrap C-style APIs that don't provide RAII resource management facilities. | |
20 | * | |
21 | * Usage example: | |
22 | * | |
23 | * // API | |
24 | * struct my_c_struct { | |
25 | * // ... | |
26 | * }; | |
27 | * | |
28 | * struct my_c_struct *create_my_c_struct(void); | |
29 | * void destroy_my_c_struct(struct my_c_struct *value); | |
30 | * | |
31 | * // Creating a unique_ptr to my_c_struct. | |
32 | * auto safe_c_struct = | |
33 | * lttng::make_unique_wrapper<my_c_struct, destroy_my_c_struct>( | |
34 | * create_my_c_struct()); | |
35 | * | |
36 | * Note that this facility is intended for use in the scope of a function. | |
37 | * If you need to return this unique_ptr instance, you should consider writting | |
38 | * a proper, idiomatic, wrapper. | |
39 | */ | |
40 | ||
41 | namespace details | |
42 | { | |
43 | template <typename WrappedType, void (*DeleterFunction)(WrappedType *)> | |
44 | struct create_unique_class { | |
45 | struct deleter { | |
46 | void operator()(WrappedType *instance) const | |
47 | { | |
48 | DeleterFunction(instance); | |
49 | } | |
50 | }; | |
51 | ||
52 | std::unique_ptr<WrappedType, deleter> operator()(WrappedType *instance) const | |
53 | { | |
54 | return std::unique_ptr<WrappedType, deleter>(instance); | |
55 | } | |
56 | }; | |
57 | } /* namespace details */ | |
58 | ||
59 | /* | |
60 | * 'free' is a utility function for use with make_unique_wrapper. It makes it easier to | |
61 | * wrap raw pointers that have to be deleted with `free`. Using libc's 'free' as | |
62 | * a make_unique_wrapper template argument will result in an error as 'WrappedType *' will | |
63 | * not match free's 'void *' argument. | |
64 | */ | |
65 | template <class Type> | |
66 | void free(Type *ptr) | |
67 | { | |
68 | std::free(ptr); | |
69 | } | |
70 | ||
71 | template <typename WrappedType, void (*DeleterFunc)(WrappedType *)> | |
72 | std::unique_ptr<WrappedType, typename details::create_unique_class<WrappedType, DeleterFunc>::deleter> | |
73 | make_unique_wrapper(WrappedType *instance) | |
74 | { | |
75 | const details::create_unique_class<WrappedType, DeleterFunc> unique_deleter; | |
76 | ||
77 | return unique_deleter(instance); | |
78 | } | |
79 | ||
80 | } /* namespace lttng */ | |
81 | ||
82 | #endif /* LTTNG_MAKE_UNIQUE_WRAPPER_H */ |