Add bt2::internal::SharedObj::create{With,Without}Ref() methods
[babeltrace.git] / src / cpp-common / bt2 / internal / shared-obj.hpp
CommitLineData
01bf7a3a
PP
1/*
2 * Copyright (c) 2019-2020 Philippe Proulx <pproulx@efficios.com>
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7#ifndef BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
8#define BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
9
10#include "common/assert.h"
11#include "cpp-common/optional.hpp"
12
13namespace bt2 {
14namespace internal {
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 *
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.
24 *
25 * `LibObjT` is the direct libbabeltrace2 object type, for example
26 * `bt_stream_class` or `const bt_value`.
27 *
28 * RefFuncsT::get() must accept a `const LibObjT *` value and increment
29 * its reference count.
30 *
31 * RefFuncsT::put() must accept a `const LibObjT *` value and decrement
32 * its reference count.
33 */
34template <typename ObjT, typename LibObjT, typename RefFuncsT>
35class SharedObj final
36{
37 /*
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 * constructor and assignment operator), given that
43 * `SpecificSomething` inherits `Something`.
44 */
45 template <typename AnyObjT, typename AnyLibObjT, typename AnyRefFuncsT>
46 friend class SharedObj;
47
c9c0b6e2
PP
48private:
49 /*
50 * Builds a shared object from `obj` without getting a reference.
51 */
52 explicit SharedObj(const ObjT& obj) noexcept : _mObj {obj}
53 {
54 }
55
01bf7a3a 56public:
c9c0b6e2
PP
57 /*
58 * Builds a shared object from `obj` without getting a reference.
59 */
60 static SharedObj createWithoutRef(const ObjT& obj) noexcept
61 {
62 return SharedObj {obj};
63 }
01bf7a3a
PP
64
65 /*
c9c0b6e2
PP
66 * Builds a shared object from `libObjPtr` without getting a
67 * reference.
01bf7a3a 68 */
c9c0b6e2 69 static SharedObj createWithoutRef(LibObjT * const libObjPtr) noexcept
01bf7a3a 70 {
c9c0b6e2 71 return SharedObj::createWithoutRef(ObjT {libObjPtr});
01bf7a3a
PP
72 }
73
74 /*
c9c0b6e2
PP
75 * Builds a shared object from `obj`, immediately getting a new
76 * reference.
01bf7a3a 77 */
c9c0b6e2 78 static SharedObj createWithRef(const ObjT& obj) noexcept
01bf7a3a 79 {
c9c0b6e2 80 SharedObj sharedObj {obj};
01bf7a3a
PP
81
82 sharedObj._getRef();
83 return sharedObj;
84 }
85
c9c0b6e2
PP
86 /*
87 * Builds a shared object from `libObjPtr`, immediately getting a new
88 * reference.
89 */
90 static SharedObj createWithRef(LibObjT * const libObjPtr) noexcept
91 {
92 return SharedObj::createWithRef(ObjT {libObjPtr});
93 }
94
01bf7a3a
PP
95 /*
96 * Generic copy constructor.
97 *
98 * See the `friend class SharedObj` comment above.
99 */
100 template <typename OtherObjT, typename OtherLibObjT>
101 SharedObj(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept :
102 _mObj {other._mObj}
103 {
104 this->_getRef();
105 }
106
107 /*
108 * Generic move constructor.
109 *
110 * See the `friend class SharedObj` comment above.
111 */
112 template <typename OtherObjT, typename OtherLibObjT>
113 SharedObj(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept : _mObj {other._mObj}
114 {
b5f55e9f 115 /* Reset moved-from object */
01bf7a3a
PP
116 other._reset();
117 }
118
119 /*
120 * Generic copy assignment operator.
121 *
122 * See the `friend class SharedObj` comment above.
123 */
124 template <typename OtherObjT, typename OtherLibObjT>
c9c0b6e2 125 SharedObj& operator=(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept
01bf7a3a 126 {
b5f55e9f 127 /* Put current object's reference */
01bf7a3a
PP
128 this->_putRef();
129
b5f55e9f 130 /* Set new current object and get a reference */
01bf7a3a
PP
131 _mObj = other._mObj;
132 this->_getRef();
133
134 return *this;
135 }
136
137 /*
138 * Generic move assignment operator.
139 *
140 * See the `friend class SharedObj` comment above.
141 */
142 template <typename OtherObjT, typename OtherLibObjT>
c9c0b6e2 143 SharedObj& operator=(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept
01bf7a3a 144 {
b5f55e9f 145 /* Put current object's reference */
01bf7a3a
PP
146 this->_putRef();
147
b5f55e9f 148 /* Set new current object */
01bf7a3a
PP
149 _mObj = other._mObj;
150
b5f55e9f 151 /* Reset moved-from object */
01bf7a3a
PP
152 other._reset();
153
154 return *this;
155 }
156
157 ~SharedObj()
158 {
159 this->_putRef();
160 }
161
162 ObjT& operator*() noexcept
163 {
164 BT_ASSERT_DBG(_mObj);
165 return *_mObj;
166 }
167
168 const ObjT& operator*() const noexcept
169 {
170 BT_ASSERT_DBG(_mObj);
171 return *_mObj;
172 }
173
174 ObjT *operator->() noexcept
175 {
176 BT_ASSERT_DBG(_mObj);
177 return &*_mObj;
178 }
179
180 const ObjT *operator->() const noexcept
181 {
182 BT_ASSERT_DBG(_mObj);
183 return &*_mObj;
184 }
185
186private:
187 /*
188 * Resets this shared object.
189 *
190 * To be used when moving it.
191 */
192 void _reset() noexcept
193 {
194 _mObj.reset();
195 }
196
197 /*
198 * Gets a new reference using the configured libbabeltrace2
199 * reference incrementation function.
200 */
201 void _getRef() const noexcept
202 {
203 if (_mObj) {
341a67c4 204 RefFuncsT::get(_mObj->libObjPtr());
01bf7a3a
PP
205 }
206 }
207
208 /*
209 * Puts a reference using the configured libbabeltrace2 reference
210 * decrementation function.
211 */
212 void _putRef() const noexcept
213 {
214 if (_mObj) {
341a67c4 215 RefFuncsT::put(_mObj->libObjPtr());
01bf7a3a
PP
216 }
217 }
218
219 nonstd::optional<ObjT> _mObj;
220};
221
b5f55e9f
PP
222} /* namespace internal */
223} /* namespace bt2 */
01bf7a3a 224
b5f55e9f 225#endif /* BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP */
This page took 0.036448 seconds and 4 git commands to generate.