2 * Copyright (c) 2019-2020 Philippe Proulx <pproulx@efficios.com>
4 * SPDX-License-Identifier: MIT
7 #ifndef BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
8 #define BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
10 #include "common/assert.h"
11 #include "cpp-common/optional.hpp"
17 * An instance of this class wraps an optional instance of `ObjT` and
18 * manages the reference counting of the underlying libbabeltrace2
21 * When you move a shared object, it becomes invalid, in that
22 * operator*() and operator->() will either fail to assert in debug mode
23 * or trigger a segmentation fault.
25 * `LibObjT` is the direct libbabeltrace2 object type, for example
26 * `bt_stream_class` or `const bt_value`.
28 * RefFuncsT::get() must accept a `const LibObjT *` value and increment
29 * its reference count.
31 * RefFuncsT::put() must accept a `const LibObjT *` value and decrement
32 * its reference count.
34 template <typename ObjT, typename LibObjT, typename RefFuncsT>
38 * This makes it possible for a
39 * `SharedObj<Something, bt_something, ...>` instance to get
40 * assigned an instance of
41 * `SharedObj<SpecificSomething, bt_something, ...>` (copy/move
42 * constructors and assignment operators), given that
43 * `SpecificSomething` inherits `Something`.
45 template <typename AnyObjT, typename AnyLibObjT, typename AnyRefFuncsT>
46 friend class SharedObj;
50 * Builds a shared object from `obj` without getting a reference.
52 explicit SharedObj(const ObjT& obj) noexcept : _mObj {obj}
57 * Common generic "copy" constructor.
59 * This constructor is meant to be delegated to by the copy
60 * constructor and the generic "copy" constructor.
62 * The second parameter, of type `int`, makes it possible to
63 * delegate by deduction as you can't explicit the template
64 * parameters when delegating to a constructor template.
66 template <typename OtherObjT, typename OtherLibObjT>
67 SharedObj(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other, int) noexcept :
74 * Common generic "move" constructor.
76 * See the comment of the common generic "copy" constructor above.
78 template <typename OtherObjT, typename OtherLibObjT>
79 SharedObj(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other, int) noexcept :
82 /* Reset moved-from object */
88 * Builds a shared object from `obj` without getting a reference.
90 static SharedObj createWithoutRef(const ObjT& obj) noexcept
92 return SharedObj {obj};
96 * Builds a shared object from `libObjPtr` without getting a
99 static SharedObj createWithoutRef(LibObjT * const libObjPtr) noexcept
101 return SharedObj::createWithoutRef(ObjT {libObjPtr});
105 * Builds a shared object from `obj`, immediately getting a new
108 static SharedObj createWithRef(const ObjT& obj) noexcept
110 SharedObj sharedObj {obj};
117 * Builds a shared object from `libObjPtr`, immediately getting a new
120 static SharedObj createWithRef(LibObjT * const libObjPtr) noexcept
122 return SharedObj::createWithRef(ObjT {libObjPtr});
128 SharedObj(const SharedObj& other) noexcept : SharedObj {other, 0}
135 SharedObj(SharedObj&& other) noexcept : SharedObj {std::move(other), 0}
140 * Copy assignment operator.
142 SharedObj& operator=(const SharedObj& other) noexcept
144 /* Use generic "copy" assignment operator */
145 return this->operator=<ObjT, LibObjT>(other);
149 * Move assignment operator.
151 SharedObj& operator=(SharedObj&& other) noexcept
153 /* Use generic "move" assignment operator */
154 return this->operator=<ObjT, LibObjT>(std::move(other));
158 * Generic "copy" constructor.
160 * See the `friend class SharedObj` comment above.
162 template <typename OtherObjT, typename OtherLibObjT>
163 SharedObj(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept :
169 * Generic "move" constructor.
171 * See the `friend class SharedObj` comment above.
173 template <typename OtherObjT, typename OtherLibObjT>
174 SharedObj(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept :
175 SharedObj {std::move(other), 0}
180 * Generic "copy" assignment operator.
182 * See the `friend class SharedObj` comment above.
184 template <typename OtherObjT, typename OtherLibObjT>
185 SharedObj& operator=(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept
187 /* Put current object's reference */
190 /* Set new current object and get a reference */
198 * Generic "move" assignment operator.
200 * See the `friend class SharedObj` comment above.
202 template <typename OtherObjT, typename OtherLibObjT>
203 SharedObj& operator=(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept
205 /* Put current object's reference */
208 /* Set new current object */
211 /* Reset moved-from object */
222 ObjT& operator*() noexcept
224 BT_ASSERT_DBG(_mObj);
228 const ObjT& operator*() const noexcept
230 BT_ASSERT_DBG(_mObj);
234 ObjT *operator->() noexcept
236 BT_ASSERT_DBG(_mObj);
240 const ObjT *operator->() const noexcept
242 BT_ASSERT_DBG(_mObj);
248 * Resets this shared object.
250 * To be used when moving it.
252 void _reset() noexcept
258 * Gets a new reference using the configured libbabeltrace2
259 * reference incrementation function.
261 void _getRef() const noexcept
264 RefFuncsT::get(_mObj->libObjPtr());
269 * Puts a reference using the configured libbabeltrace2 reference
270 * decrementation function.
272 void _putRef() const noexcept
275 RefFuncsT::put(_mObj->libObjPtr());
279 nonstd::optional<ObjT> _mObj;
282 } /* namespace internal */
283 } /* namespace bt2 */
285 #endif /* BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP */