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