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. | |
74021af6 | 37 | * If you need to return this unique_ptr instance, you should consider writing |
8802d23b JG |
38 | * a proper, idiomatic, wrapper. |
39 | */ | |
40 | ||
f053d40c | 41 | namespace memory { |
8802d23b | 42 | template <typename WrappedType, void (*DeleterFunction)(WrappedType *)> |
f053d40c | 43 | struct create_deleter_class { |
8802d23b JG |
44 | struct deleter { |
45 | void operator()(WrappedType *instance) const | |
46 | { | |
47 | DeleterFunction(instance); | |
48 | } | |
49 | }; | |
50 | ||
51 | std::unique_ptr<WrappedType, deleter> operator()(WrappedType *instance) const | |
52 | { | |
53 | return std::unique_ptr<WrappedType, deleter>(instance); | |
54 | } | |
55 | }; | |
8802d23b JG |
56 | |
57 | /* | |
58 | * 'free' is a utility function for use with make_unique_wrapper. It makes it easier to | |
59 | * wrap raw pointers that have to be deleted with `free`. Using libc's 'free' as | |
60 | * a make_unique_wrapper template argument will result in an error as 'WrappedType *' will | |
61 | * not match free's 'void *' argument. | |
62 | */ | |
63 | template <class Type> | |
64 | void free(Type *ptr) | |
65 | { | |
66 | std::free(ptr); | |
67 | } | |
303ac4ed | 68 | } /* namespace memory */ |
8802d23b JG |
69 | |
70 | template <typename WrappedType, void (*DeleterFunc)(WrappedType *)> | |
28f23191 | 71 | std::unique_ptr<WrappedType, |
f053d40c | 72 | typename memory::create_deleter_class<WrappedType, DeleterFunc>::deleter> |
799462ff | 73 | make_unique_wrapper(WrappedType *instance = nullptr) |
8802d23b | 74 | { |
f053d40c | 75 | const memory::create_deleter_class<WrappedType, DeleterFunc> unique_deleter; |
8802d23b JG |
76 | |
77 | return unique_deleter(instance); | |
78 | } | |
79 | ||
80 | } /* namespace lttng */ | |
81 | ||
82 | #endif /* LTTNG_MAKE_UNIQUE_WRAPPER_H */ |