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
12 #include "common/assert.h"
14 #include "optional-borrowed-object.hpp"
19 * An instance of this class wraps an optional instance of `ObjT` and
20 * manages the reference counting of the underlying libbabeltrace2
23 * When you move a shared object, it becomes empty, in that operator*()
24 * and operator->() will either fail to assert in debug mode or trigger
25 * a segmentation fault.
27 * The default constructor builds an empty shared object. You may also
28 * call the reset() method to make a shared object empty. Check whether
29 * or not a shared object is empty with the `bool` operator.
31 * `LibObjT` is the direct libbabeltrace2 object type, for example
32 * `bt_stream_class` or `const bt_value`.
34 * RefFuncsT::get() must accept a `const LibObjT *` value and increment
35 * its reference count.
37 * RefFuncsT::put() must accept a `const LibObjT *` value and decrement
38 * its reference count.
40 template <typename ObjT, typename LibObjT, typename RefFuncsT>
41 class SharedObject final
44 * This makes it possible for a
45 * `SharedObject<Something, bt_something, ...>` instance to get
46 * assigned an instance of
47 * `SharedObject<SpecificSomething, bt_something, ...>` (copy/move
48 * constructors and assignment operators), given that
49 * `SpecificSomething` inherits `Something`.
51 template <typename, typename, typename>
52 friend class SharedObject;
56 * Builds an empty shared object.
58 explicit SharedObject() noexcept
64 * Builds a shared object from `obj` without getting a reference.
66 explicit SharedObject(const ObjT& obj) noexcept : _mObj {obj}
71 * Common generic "copy" constructor.
73 * This constructor is meant to be delegated to by the copy
74 * constructor and the generic "copy" constructor.
76 * The second parameter, of type `int`, makes it possible to
77 * delegate by deduction as you can't explicit the template
78 * parameters when delegating to a constructor template.
80 template <typename OtherObjT, typename OtherLibObjT>
81 SharedObject(const SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>& other, int) noexcept :
88 * Common generic "move" constructor.
90 * See the comment of the common generic "copy" constructor above.
92 template <typename OtherObjT, typename OtherLibObjT>
93 SharedObject(SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>&& other, int) noexcept :
96 /* Reset moved-from object */
102 * Builds a shared object from `obj` without getting a reference.
104 static SharedObject createWithoutRef(const ObjT& obj) noexcept
106 return SharedObject {obj};
110 * Builds a shared object from `libObjPtr` without getting a
113 static SharedObject createWithoutRef(LibObjT * const libObjPtr) noexcept
115 return SharedObject::createWithoutRef(ObjT {libObjPtr});
119 * Builds a shared object from `obj`, immediately getting a new
122 static SharedObject createWithRef(const ObjT& obj) noexcept
124 SharedObject sharedObj {obj};
131 * Builds a shared object from `libObjPtr`, immediately getting a
134 static SharedObject createWithRef(LibObjT * const libObjPtr) noexcept
136 return SharedObject::createWithRef(ObjT {libObjPtr});
142 SharedObject(const SharedObject& other) noexcept : SharedObject {other, 0}
149 SharedObject(SharedObject&& other) noexcept : SharedObject {std::move(other), 0}
154 * Copy assignment operator.
156 SharedObject& operator=(const SharedObject& other) noexcept
158 /* Use generic "copy" assignment operator */
159 return this->operator=<ObjT, LibObjT>(other);
163 * Move assignment operator.
165 SharedObject& operator=(SharedObject&& other) noexcept
167 /* Use generic "move" assignment operator */
168 return this->operator=<ObjT, LibObjT>(std::move(other));
172 * Generic "copy" constructor.
174 * See the `friend class SharedObject` comment above.
176 template <typename OtherObjT, typename OtherLibObjT>
177 SharedObject(const SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept :
178 SharedObject {other, 0}
183 * Generic "move" constructor.
185 * See the `friend class SharedObject` comment above.
187 template <typename OtherObjT, typename OtherLibObjT>
188 SharedObject(SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept :
189 SharedObject {std::move(other), 0}
194 * Generic "copy" assignment operator.
196 * See the `friend class SharedObject` comment above.
198 template <typename OtherObjT, typename OtherLibObjT>
199 SharedObject& operator=(const SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept
201 /* Put current object's reference */
204 /* Set new current object and get a reference */
212 * Generic "move" assignment operator.
214 * See the `friend class SharedObject` comment above.
216 template <typename OtherObjT, typename OtherLibObjT>
217 SharedObject& operator=(SharedObject<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept
219 /* Put current object's reference */
222 /* Set new current object */
225 /* Reset moved-from object */
236 ObjT operator*() const noexcept
238 BT_ASSERT_DBG(_mObj);
242 BorrowedObjectProxy<ObjT> operator->() const noexcept
244 BT_ASSERT_DBG(_mObj);
245 return _mObj.operator->();
248 operator bool() const noexcept
250 return _mObj.hasObject();
254 * Makes this shared object empty.
256 void reset() noexcept
265 * Transfers the reference of the object which this shared object
266 * wrapper manages and returns it, making the caller become an
269 * This method makes this object empty.
271 ObjT release() noexcept
273 BT_ASSERT_DBG(_mObj);
275 const auto obj = *_mObj;
283 * Resets this shared object.
285 * To be used when moving it.
287 void _reset() noexcept
293 * Gets a new reference using the configured libbabeltrace2
294 * reference incrementation function.
296 void _getRef() const noexcept
298 RefFuncsT::get(_mObj.libObjPtr());
302 * Puts a reference using the configured libbabeltrace2 reference
303 * decrementation function.
305 void _putRef() const noexcept
307 RefFuncsT::put(_mObj.libObjPtr());
310 OptionalBorrowedObject<ObjT> _mObj;
313 } /* namespace bt2 */
315 #endif /* BABELTRACE_CPP_COMMON_BT2_SHARED_OBJECT_HPP */