Add libbabeltrace2 C++ interface base
[babeltrace.git] / src / cpp-common / bt2 / internal / shared-obj.hpp
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
13 namespace bt2 {
14 namespace 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 */
34 template <typename ObjT, typename LibObjT, typename RefFuncsT>
35 class 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
48 public:
49 // This complete shared object
50 using ThisSharedObj = SharedObj<ObjT, LibObjT, RefFuncsT>;
51
52 /*
53 * Builds a shared object from `obj` without an initial reference.
54 *
55 * Use this constructor to build a shared object wrapping a newly
56 * created libbabeltrace2 object.
57 *
58 * Use createWithInitialRef() to build a shared object having an
59 * initial reference count.
60 */
61 explicit SharedObj(const ObjT& obj) noexcept : _mObj {obj}
62 {
63 }
64
65 /*
66 * Builds a shared object from `obj` with an initial reference.
67 *
68 * Use this constructor to build a shared object wrapping a newly
69 * created libbabeltrace2 object.
70 */
71 static ThisSharedObj createWithInitialRef(const ObjT& obj) noexcept
72 {
73 ThisSharedObj sharedObj {obj};
74
75 sharedObj._getRef();
76 return sharedObj;
77 }
78
79 /*
80 * Generic copy constructor.
81 *
82 * See the `friend class SharedObj` comment above.
83 */
84 template <typename OtherObjT, typename OtherLibObjT>
85 SharedObj(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept :
86 _mObj {other._mObj}
87 {
88 this->_getRef();
89 }
90
91 /*
92 * Generic move constructor.
93 *
94 * See the `friend class SharedObj` comment above.
95 */
96 template <typename OtherObjT, typename OtherLibObjT>
97 SharedObj(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept : _mObj {other._mObj}
98 {
99 // Reset moved-from object
100 other._reset();
101 }
102
103 /*
104 * Generic copy assignment operator.
105 *
106 * See the `friend class SharedObj` comment above.
107 */
108 template <typename OtherObjT, typename OtherLibObjT>
109 ThisSharedObj& operator=(const SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>& other) noexcept
110 {
111 // Put current object's reference
112 this->_putRef();
113
114 // Set new current object and get a reference
115 _mObj = other._mObj;
116 this->_getRef();
117
118 return *this;
119 }
120
121 /*
122 * Generic move assignment operator.
123 *
124 * See the `friend class SharedObj` comment above.
125 */
126 template <typename OtherObjT, typename OtherLibObjT>
127 ThisSharedObj& operator=(SharedObj<OtherObjT, OtherLibObjT, RefFuncsT>&& other) noexcept
128 {
129 // Put current object's reference
130 this->_putRef();
131
132 // Set new current object
133 _mObj = other._mObj;
134
135 // Reset moved-from object
136 other._reset();
137
138 return *this;
139 }
140
141 ~SharedObj()
142 {
143 this->_putRef();
144 }
145
146 ObjT& operator*() noexcept
147 {
148 BT_ASSERT_DBG(_mObj);
149 return *_mObj;
150 }
151
152 const ObjT& operator*() const noexcept
153 {
154 BT_ASSERT_DBG(_mObj);
155 return *_mObj;
156 }
157
158 ObjT *operator->() noexcept
159 {
160 BT_ASSERT_DBG(_mObj);
161 return &*_mObj;
162 }
163
164 const ObjT *operator->() const noexcept
165 {
166 BT_ASSERT_DBG(_mObj);
167 return &*_mObj;
168 }
169
170 private:
171 /*
172 * Resets this shared object.
173 *
174 * To be used when moving it.
175 */
176 void _reset() noexcept
177 {
178 _mObj.reset();
179 }
180
181 /*
182 * Gets a new reference using the configured libbabeltrace2
183 * reference incrementation function.
184 */
185 void _getRef() const noexcept
186 {
187 if (_mObj) {
188 RefFuncsT::get(_mObj->_libObjPtr());
189 }
190 }
191
192 /*
193 * Puts a reference using the configured libbabeltrace2 reference
194 * decrementation function.
195 */
196 void _putRef() const noexcept
197 {
198 if (_mObj) {
199 RefFuncsT::put(_mObj->_libObjPtr());
200 }
201 }
202
203 nonstd::optional<ObjT> _mObj;
204 };
205
206 } // namespace internal
207 } // namespace bt2
208
209 #endif // BABELTRACE_CPP_COMMON_BT2_INTERNAL_SHARED_OBJ_HPP
This page took 0.033819 seconds and 4 git commands to generate.