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