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