cpp-common/bt2: rename `bt2::BorrowedObj` -> `bt2::BorrowedObject`
[babeltrace.git] / src / cpp-common / bt2 / internal / shared-obj.hpp
CommitLineData
01bf7a3a
PP
1/*
2 * Copyright (c) 2019-2020 Philippe Proulx <pproulx@efficios.com>
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#ifndef BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
8#define BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
9
10#include "common/assert.h"
11#include "cpp-common/optional.hpp"
12
13namespace bt2 {
14namespace internal {
15
16/*
17 * An instance of this class wraps an optional instance of `ObjT` and
18 * manages the reference counting of the underlying libbabeltrace2
19 * object.
20 *
21 * When you move a shared object, it becomes invalid, in that
22 * operator*() and operator->() will either fail to assert in debug mode
23 * or trigger a segmentation fault.
24 *
25 * `LibObjT` is the direct libbabeltrace2 object type, for example
26 * `bt_stream_class` or `const bt_value`.
27 *
28 * RefFuncsT::get() must accept a `const LibObjT *` value and increment
29 * its reference count.
30 *
31 * RefFuncsT::put() must accept a `const LibObjT *` value and decrement
32 * its reference count.
33 */
34template <typename ObjT, typename LibObjT, typename RefFuncsT>
35class SharedObj final
36{
37 /*
38 * This makes it possible for a
39 * `SharedObj<Something, bt_something, ...>` instance to get
40 * assigned an instance of
41 * `SharedObj<SpecificSomething, bt_something, ...>` (copy/move
e60a53f1 42 * constructors and assignment operators), given that
01bf7a3a
PP
43 * `SpecificSomething` inherits `Something`.
44 */
96643d28 45 template <typename, typename, typename>
01bf7a3a
PP
46 friend class SharedObj;
47
c9c0b6e2
PP
48private:
49 /*
50 * Builds a shared object from `obj` without getting a reference.
51 */
52 explicit SharedObj(const ObjT& obj) noexcept : _mObj {obj}
53 {
54 }
55
e60a53f1
PP
56 /*
57 * Common generic "copy" constructor.
58 *
59 * This constructor is meant to be delegated to by the copy
60 * constructor and the generic "copy" constructor.
61 *
62 * The second parameter, of type `int`, makes it possible to
63 * delegate by deduction as you can't explicit the template
64 * parameters when delegating to a constructor template.
65 */
66 template <typename OtherObjT, typename OtherLibObjT>
67 SharedObj(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other, int) noexcept :
68 _mObj {other._mObj}
69 {
70 this->_getRef();
71 }
72
73 /*
74 * Common generic "move" constructor.
75 *
76 * See the comment of the common generic "copy" constructor above.
77 */
78 template <typename OtherObjT, typename OtherLibObjT>
79 SharedObj(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other, int) noexcept :
80 _mObj {other._mObj}
81 {
82 /* Reset moved-from object */
83 other._reset();
84 }
85
01bf7a3a 86public:
c9c0b6e2
PP
87 /*
88 * Builds a shared object from `obj` without getting a reference.
89 */
90 static SharedObj createWithoutRef(const ObjT& obj) noexcept
91 {
92 return SharedObj {obj};
93 }
01bf7a3a
PP
94
95 /*
c9c0b6e2
PP
96 * Builds a shared object from `libObjPtr` without getting a
97 * reference.
01bf7a3a 98 */
c9c0b6e2 99 static SharedObj createWithoutRef(LibObjT * const libObjPtr) noexcept
01bf7a3a 100 {
c9c0b6e2 101 return SharedObj::createWithoutRef(ObjT {libObjPtr});
01bf7a3a
PP
102 }
103
104 /*
c9c0b6e2
PP
105 * Builds a shared object from `obj`, immediately getting a new
106 * reference.
01bf7a3a 107 */
c9c0b6e2 108 static SharedObj createWithRef(const ObjT& obj) noexcept
01bf7a3a 109 {
c9c0b6e2 110 SharedObj sharedObj {obj};
01bf7a3a
PP
111
112 sharedObj._getRef();
113 return sharedObj;
114 }
115
c9c0b6e2
PP
116 /*
117 * Builds a shared object from `libObjPtr`, immediately getting a new
118 * reference.
119 */
120 static SharedObj createWithRef(LibObjT * const libObjPtr) noexcept
121 {
122 return SharedObj::createWithRef(ObjT {libObjPtr});
123 }
124
01bf7a3a 125 /*
e60a53f1
PP
126 * Copy constructor.
127 */
128 SharedObj(const SharedObj& other) noexcept : SharedObj {other, 0}
129 {
130 }
131
132 /*
133 * Move constructor.
134 */
135 SharedObj(SharedObj&& other) noexcept : SharedObj {std::move(other), 0}
136 {
137 }
138
139 /*
140 * Copy assignment operator.
141 */
142 SharedObj& operator=(const SharedObj& other) noexcept
143 {
144 /* Use generic "copy" assignment operator */
145 return this->operator=<ObjT, LibObjT>(other);
146 }
147
148 /*
149 * Move assignment operator.
150 */
151 SharedObj& operator=(SharedObj&& other) noexcept
152 {
153 /* Use generic "move" assignment operator */
154 return this->operator=<ObjT, LibObjT>(std::move(other));
155 }
156
157 /*
158 * Generic "copy" constructor.
01bf7a3a
PP
159 *
160 * See the `friend class SharedObj` comment above.
161 */
162 template <typename OtherObjT, typename OtherLibObjT>
163 SharedObj(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept :
e60a53f1 164 SharedObj {other, 0}
01bf7a3a 165 {
01bf7a3a
PP
166 }
167
168 /*
e60a53f1 169 * Generic "move" constructor.
01bf7a3a
PP
170 *
171 * See the `friend class SharedObj` comment above.
172 */
173 template <typename OtherObjT, typename OtherLibObjT>
e60a53f1
PP
174 SharedObj(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept :
175 SharedObj {std::move(other), 0}
01bf7a3a 176 {
01bf7a3a
PP
177 }
178
179 /*
e60a53f1 180 * Generic "copy" assignment operator.
01bf7a3a
PP
181 *
182 * See the `friend class SharedObj` comment above.
183 */
184 template <typename OtherObjT, typename OtherLibObjT>
c9c0b6e2 185 SharedObj& operator=(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept
01bf7a3a 186 {
b5f55e9f 187 /* Put current object's reference */
01bf7a3a
PP
188 this->_putRef();
189
b5f55e9f 190 /* Set new current object and get a reference */
01bf7a3a
PP
191 _mObj = other._mObj;
192 this->_getRef();
193
194 return *this;
195 }
196
197 /*
e60a53f1 198 * Generic "move" assignment operator.
01bf7a3a
PP
199 *
200 * See the `friend class SharedObj` comment above.
201 */
202 template <typename OtherObjT, typename OtherLibObjT>
c9c0b6e2 203 SharedObj& operator=(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept
01bf7a3a 204 {
b5f55e9f 205 /* Put current object's reference */
01bf7a3a
PP
206 this->_putRef();
207
b5f55e9f 208 /* Set new current object */
01bf7a3a
PP
209 _mObj = other._mObj;
210
b5f55e9f 211 /* Reset moved-from object */
01bf7a3a
PP
212 other._reset();
213
214 return *this;
215 }
216
217 ~SharedObj()
218 {
219 this->_putRef();
220 }
221
222 ObjT& operator*() noexcept
223 {
224 BT_ASSERT_DBG(_mObj);
225 return *_mObj;
226 }
227
228 const ObjT& operator*() const noexcept
229 {
230 BT_ASSERT_DBG(_mObj);
231 return *_mObj;
232 }
233
234 ObjT *operator->() noexcept
235 {
236 BT_ASSERT_DBG(_mObj);
237 return &*_mObj;
238 }
239
240 const ObjT *operator->() const noexcept
241 {
242 BT_ASSERT_DBG(_mObj);
243 return &*_mObj;
244 }
245
d0b6533a
SM
246 /*
247 * Transfers the reference of the object which this shared object
248 * wrapper manages and returns it, making the caller become an active
249 * owner.
250 *
251 * This method makes this object invalid.
252 */
253 ObjT release() noexcept
254 {
255 BT_ASSERT_DBG(_mObj);
256 const auto obj = *_mObj;
257 this->_reset();
258 return obj;
259 }
260
01bf7a3a
PP
261private:
262 /*
263 * Resets this shared object.
264 *
265 * To be used when moving it.
266 */
267 void _reset() noexcept
268 {
269 _mObj.reset();
270 }
271
272 /*
273 * Gets a new reference using the configured libbabeltrace2
274 * reference incrementation function.
275 */
276 void _getRef() const noexcept
277 {
278 if (_mObj) {
341a67c4 279 RefFuncsT::get(_mObj->libObjPtr());
01bf7a3a
PP
280 }
281 }
282
283 /*
284 * Puts a reference using the configured libbabeltrace2 reference
285 * decrementation function.
286 */
287 void _putRef() const noexcept
288 {
289 if (_mObj) {
341a67c4 290 RefFuncsT::put(_mObj->libObjPtr());
01bf7a3a
PP
291 }
292 }
293
294 nonstd::optional<ObjT> _mObj;
295};
296
b5f55e9f
PP
297} /* namespace internal */
298} /* namespace bt2 */
01bf7a3a 299
b5f55e9f 300#endif /* BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP */
This page took 0.043666 seconds and 4 git commands to generate.