2 * Copyright (c) 2019-2020 Philippe Proulx <pproulx@efficios.com>
4 * SPDX-License-Identifier: MIT
7 #ifndef BABELTRACE_CPP_COMMON_BT2_SHARED_OBJECT_HPP
8 #define BABELTRACE_CPP_COMMON_BT2_SHARED_OBJECT_HPP
10 #include "common/assert.h"
11 #include "cpp-common/optional.hpp"
16 * An instance of this class wraps an optional instance of `ObjT` and
17 * manages the reference counting of the underlying libbabeltrace2
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.
24 * `LibObjT` is the direct libbabeltrace2 object type, for example
25 * `bt_stream_class` or `const bt_value`.
27 * RefFuncsT::get() must accept a `const LibObjT *` value and increment
28 * its reference count.
30 * RefFuncsT::put() must accept a `const LibObjT *` value and decrement
31 * its reference count.
33 template <typename ObjT, typename LibObjT, typename RefFuncsT>
34 class SharedObject final
37 * This makes it possible for a
38 * `SharedObject<Something, bt_something, ...>` instance to get
39 * assigned an instance of
40 * `SharedObject<SpecificSomething, bt_something, ...>` (copy/move
41 * constructors and assignment operators), given that
42 * `SpecificSomething` inherits `Something`.
44 template <typename, typename, typename>
45 friend class SharedObject;
49 * Builds a shared object from `obj` without getting a reference.
51 explicit SharedObject(const ObjT& obj) noexcept : _mObj {obj}
56 * Common generic "copy" constructor.
58 * This constructor is meant to be delegated to by the copy
59 * constructor and the generic "copy" constructor.
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.
65 template <typename OtherObjT, typename OtherLibObjT>
66 SharedObject(const SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>& other, int) noexcept :
73 * Common generic "move" constructor.
75 * See the comment of the common generic "copy" constructor above.
77 template <typename OtherObjT, typename OtherLibObjT>
78 SharedObject(SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>&& other, int) noexcept :
81 /* Reset moved-from object */
87 * Builds a shared object from `obj` without getting a reference.
89 static SharedObject createWithoutRef(const ObjT& obj) noexcept
91 return SharedObject {obj};
95 * Builds a shared object from `libObjPtr` without getting a
98 static SharedObject createWithoutRef(LibObjT * const libObjPtr) noexcept
100 return SharedObject::createWithoutRef(ObjT {libObjPtr});
104 * Builds a shared object from `obj`, immediately getting a new
107 static SharedObject createWithRef(const ObjT& obj) noexcept
109 SharedObject sharedObj {obj};
116 * Builds a shared object from `libObjPtr`, immediately getting a
119 static SharedObject createWithRef(LibObjT * const libObjPtr) noexcept
121 return SharedObject::createWithRef(ObjT {libObjPtr});
127 SharedObject(const SharedObject& other) noexcept : SharedObject {other, 0}
134 SharedObject(SharedObject&& other) noexcept : SharedObject {std::move(other), 0}
139 * Copy assignment operator.
141 SharedObject& operator=(const SharedObject& other) noexcept
143 /* Use generic "copy" assignment operator */
144 return this->operator=<ObjT, LibObjT>(other);
148 * Move assignment operator.
150 SharedObject& operator=(SharedObject&& other) noexcept
152 /* Use generic "move" assignment operator */
153 return this->operator=<ObjT, LibObjT>(std::move(other));
157 * Generic "copy" constructor.
159 * See the `friend class SharedObject` comment above.
161 template <typename OtherObjT, typename OtherLibObjT>
162 SharedObject(const SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept :
163 SharedObject {other, 0}
168 * Generic "move" constructor.
170 * See the `friend class SharedObject` comment above.
172 template <typename OtherObjT, typename OtherLibObjT>
173 SharedObject(SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept :
174 SharedObject {std::move(other), 0}
179 * Generic "copy" assignment operator.
181 * See the `friend class SharedObject` comment above.
183 template <typename OtherObjT, typename OtherLibObjT>
184 SharedObject& operator=(const SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept
186 /* Put current object's reference */
189 /* Set new current object and get a reference */
197 * Generic "move" assignment operator.
199 * See the `friend class SharedObject` comment above.
201 template <typename OtherObjT, typename OtherLibObjT>
202 SharedObject& operator=(SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept
204 /* Put current object's reference */
207 /* Set new current object */
210 /* Reset moved-from object */
221 ObjT& operator*() noexcept
223 BT_ASSERT_DBG(_mObj);
227 const ObjT& operator*() const noexcept
229 BT_ASSERT_DBG(_mObj);
233 ObjT *operator->() noexcept
235 BT_ASSERT_DBG(_mObj);
239 const ObjT *operator->() const noexcept
241 BT_ASSERT_DBG(_mObj);
246 * Transfers the reference of the object which this shared object
247 * wrapper manages and returns it, making the caller become an
250 * This method makes this object invalid.
252 ObjT release() noexcept
254 BT_ASSERT_DBG(_mObj);
256 const auto obj = *_mObj;
264 * Resets this shared object.
266 * To be used when moving it.
268 void _reset() noexcept
274 * Gets a new reference using the configured libbabeltrace2
275 * reference incrementation function.
277 void _getRef() const noexcept
280 RefFuncsT::get(_mObj->libObjPtr());
285 * Puts a reference using the configured libbabeltrace2 reference
286 * decrementation function.
288 void _putRef() const noexcept
291 RefFuncsT::put(_mObj->libObjPtr());
295 nonstd::optional<ObjT> _mObj;
298 } /* namespace bt2 */
300 #endif /* BABELTRACE_CPP_COMMON_BT2_SHARED_OBJECT_HPP */