ADTF
Loading...
Searching...
No Matches
object_ptr.h
Go to the documentation of this file.
1
7#pragma once
8
9#include "object_ptr_intf.h"
10
11namespace adtf
12{
13namespace ucom
14{
15namespace ant
16{
17
18template<typename T>
19class weak_object_ptr;
20
21namespace detail
22{
23template<typename StorageType>
24class object_ptr_storage
25{
26public:
27 constexpr object_ptr_storage() noexcept: m_pObject(nullptr), m_pRefer(nullptr)
28 {
29 }
30
31 constexpr object_ptr_storage(::std::nullptr_t) noexcept: object_ptr_storage()
32 {
33 }
34
35 object_ptr_storage(iobject_ptr_ref<size_t>* pControlBlock,
36 StorageType* pSharedObject,
37 bool bFromWeak = false) noexcept:
38 m_pObject(pSharedObject), m_pRefer(pSharedObject ? pControlBlock : nullptr)
39 {
40 if (m_pRefer)
41 {
42 if (bFromWeak)
43 {
44 if (!m_pRefer->IncreaseUseCountNonZero())
45 {
46 m_pObject = nullptr;
47 m_pRefer = nullptr;
48 }
49 }
50 else
51 {
52 m_pRefer->IncreaseUseCount();
53 }
54 }
55 }
56
57 object_ptr_storage(const object_ptr_storage& oOther) noexcept:
58 object_ptr_storage(oOther.GetObjPtrRef(), oOther.GetStorageObject())
59 {
60 }
61
62 template<typename U,
63 typename ConstCompatible = ::std::enable_if_t<::std::is_const_v<StorageType> || !::std::is_const_v<U>>>
64 object_ptr_storage(const iobject_ptr<U>& oOther) noexcept:
65 object_ptr_storage(oOther.GetObjPtrRef(), ucom_cast<StorageType*>(oOther.Get()))
66 {
67 }
68
69 template<typename U,
70 typename ConstCompatible = ::std::enable_if_t<std::is_const_v<StorageType> || !::std::is_const_v<U>>>
71 object_ptr_storage(const weak_object_ptr<U>& oWeak) noexcept:
72 object_ptr_storage(oWeak.m_pRefer, oWeak.m_pObject, true)
73 {
74 }
75
76 object_ptr_storage(const iobject_ptr<StorageType>& oOther) noexcept:
77 object_ptr_storage(oOther.GetObjPtrRef(), oOther.Get())
78 {
79 }
80
82 template<typename U>
83 object_ptr_storage(const iobject_ptr<U>& i_oOther, StorageType* pSharedObject) noexcept:
84 object_ptr_storage(i_oOther.GetObjPtrRef(), pSharedObject)
85 {
86 }
87
89 {
90 Reset();
91 }
92
93 constexpr detail::iobject_ptr_ref<size_t>* GetObjPtrRef() const noexcept
94 {
95 return m_pRefer;
96 }
97
98 constexpr StorageType* GetStorageObject() const noexcept
99 {
100 return m_pObject;
101 }
102
103 object_ptr_storage& operator=(const object_ptr_storage& oOther)
104 {
105 object_ptr_storage oHelper(oOther);
106 Swap(oHelper);
107 return *this;
108 }
109
110 object_ptr_storage& operator=(object_ptr_storage&& oOther)
111 {
112 Swap(oOther);
113 // Not strictly neccessary by operator definition, but tests require this.
114 // Has unintended side effect of making the move assignment throwing.
115 oOther.Reset();
116 return *this;
117 }
118
119 void Reset()
120 {
121 if (m_pRefer)
122 {
123 auto pOrphanedBlock = m_pRefer;
124 m_pRefer = nullptr;
125 m_pObject = nullptr;
126 // If the destructor of iobject_ptr_ref is throwing, then Reset() is throwing too.
127 pOrphanedBlock->DecreaseUseCount();
128 }
129 }
130
131 void Swap(object_ptr_storage& oOther) noexcept
132 {
133 using ::std::swap;
134 swap(m_pObject, oOther.m_pObject);
135 swap(m_pRefer, oOther.m_pRefer);
136 }
137
138private:
139 StorageType* m_pObject;
140 detail::iobject_ptr_ref<size_t>* m_pRefer;
141};
142
143template<typename StorageType>
145template<typename StorageType>
147template<typename T, typename StorageType>
149template<typename T, typename StorageType>
151
152template<typename T, typename StorageType>
153using object_ptr_base =
154 typename ::std::conditional_t<::std::is_same_v<std::remove_const_t<T>, IObject>,
155 ::std::conditional_t<::std::is_const_v<T>,
158 ::std::conditional_t<::std::is_const_v<T>,
161
162template<typename T, typename StorageType>
163class object_ptr_delegate_base : public iobject_ptr<T>
164{
165 static_assert(!::std::is_volatile_v<T> && !::std::is_reference_v<T>);
166 static_assert(!::std::is_volatile_v<StorageType> && !::std::is_reference_v<StorageType>);
167 static_assert(::std::is_const_v<T> || !::std::is_const_v<StorageType>,
168 "Can't enable non-const interface for a const storage type");
169
170public:
171 template<typename... Args>
172 object_ptr_delegate_base(Args&&... args) noexcept: m_oDelegate(::std::forward<Args>(args)...)
173 {
174 }
175
176 object_ptr_delegate_base(const object_ptr_delegate_base& oOther) noexcept:
177 object_ptr_delegate_base(oOther, oOther.GetStorageObject())
178 {
179 }
180
181 object_ptr_delegate_base(object_ptr_delegate_base&& oOther) noexcept: object_ptr_delegate_base()
182 {
183 Swap(oOther);
184 }
185
186 ~object_ptr_delegate_base() = default;
187
188 constexpr detail::iobject_ptr_ref<size_t>* GetObjPtrRef() const noexcept final override
189 {
190 return m_oDelegate.GetObjPtrRef();
191 }
192
193 constexpr StorageType* GetStorageObject() const noexcept
194 {
195 return m_oDelegate.GetStorageObject();
196 }
197
198 T* Get() const final override
199 {
200 if constexpr (::std::is_same_v<T, StorageType>)
201 {
202 return GetStorageObject();
203 }
204 else
205 {
206 return ucom_cast<T*>(GetStorageObject());
207 }
208 }
209
210 T* operator->() const noexcept final override
211 {
212 return Get();
213 }
214
215 T& operator*() const noexcept
216 {
217 return *Get();
218 }
219
220 void Swap(object_ptr_delegate_base& oOther) noexcept
221 {
222 m_oDelegate.Swap(oOther.m_oDelegate);
223 }
224
225 void Reset()
226 {
227 m_oDelegate.Reset();
228 }
229
230 tResult Reset(const iobject_ptr<T>& oOther) noexcept final override
231 {
232 RETURN_IF_THROWS(Reset());
233
234 if (!oOther.Get())
235 {
237 }
238 else if constexpr (::std::is_same_v<T, StorageType>)
239 {
240 object_ptr_base<T, StorageType> oHelper(oOther);
241 Swap(oHelper);
243 }
244#ifdef _MSC_VER
245#pragma warning(push)
246#pragma warning(disable : 6326) // Potential comparison of a constant with another constant
247#endif
248 else if constexpr (::std::is_same_v<std::remove_const_t<T>, IObject> &&
249 ::std::is_const_v<StorageType> == ::std::is_const_v<T> &&
250 has_interface_info_type<::std::remove_const_t<StorageType>>::value)
251#ifdef _MSC_VER
252#pragma warning(pop)
253#endif
254 {
255 const auto pObject = ucom_cast<StorageType*>(oOther.Get());
256 if (!pObject)
257 {
258 RETURN_ERROR_DESC(ERR_NO_INTERFACE, "Object does not implement interface '%s'.",
260 }
261
262 object_ptr_base<T, StorageType> oHelper(oOther, pObject);
263 Swap(oHelper);
265 }
266 else
267 {
268 RETURN_ERROR(ERR_NO_INTERFACE);
269 }
270 }
271
272 object_ptr_delegate_base& operator=(const object_ptr_delegate_base& oOther)
273 {
274 m_oDelegate = oOther.m_oDelegate;
275 return *this;
276 }
277
278 object_ptr_delegate_base& operator=(object_ptr_delegate_base&& oOther)
279 {
280 m_oDelegate = ::std::move(oOther.m_oDelegate);
281 return *this;
282 }
283
284 constexpr explicit operator bool() const noexcept
285 {
286 return (GetStorageObject() != nullptr);
287 }
288
289protected:
290 ::std::conditional_t<::std::is_same_v<std::remove_const_t<T>, IObject>,
291 std::conditional_t<!::std::is_const_v<T> && !::std::is_const_v<StorageType>,
292 object_ptr_const_iobject_delegate<StorageType>,
293 object_ptr_storage<StorageType>>,
294 std::conditional_t<::std::is_const_v<T> || ::std::is_const_v<StorageType>,
295 ::std::conditional_t<::std::is_const_v<StorageType>,
296 object_ptr_const_iobject_delegate<StorageType>,
297 object_ptr_iobject_delegate<StorageType>>,
298 object_ptr_const_delegate<const T, StorageType>>>
299 m_oDelegate;
300};
301
302template<typename StorageType>
303class object_ptr_const_iobject_delegate : public object_ptr_delegate_base<const IObject, StorageType>
304{
305public:
306 using object_ptr_delegate_base<const IObject, StorageType>::object_ptr_delegate_base;
307};
308
309template<typename StorageType>
310class object_ptr_iobject_delegate : public object_ptr_delegate_base<IObject, StorageType>
311{
312 using base = object_ptr_delegate_base<IObject, StorageType>;
313public:
314 using base::base;
315
316 constexpr operator const iobject_ptr<const IObject>&() const noexcept final override
317 {
318 return base::m_oDelegate;
319 }
320};
321
322template<typename T, typename StorageType>
323class object_ptr_const_delegate : public object_ptr_delegate_base<T, StorageType>
324{
325 static_assert(::std::is_const_v<T> && !::std::is_same_v<T, const IObject>);
326
327 using base = object_ptr_delegate_base<T, StorageType>;
328public:
329 using base::base;
330
331 constexpr operator const iobject_ptr<const IObject>&() const noexcept
332 {
333 return base::m_oDelegate;
334 }
335
336 template<typename U, typename = ::std::enable_if_t<::std::is_same_v<U, IObject> && !::std::is_const_v<StorageType>>>
337 constexpr operator const iobject_ptr<U>&() const noexcept
338 {
339 return base::m_oDelegate;
340 }
341
342 template<typename U,
343 typename = std::enable_if_t<(::std::is_same_v<U, const IObject> && ::std::is_const_v<StorageType>) ||
344 (::std::is_same_v<U, IObject> && !::std::is_const_v<StorageType>)>>
345 constexpr operator iobject_ptr<U>&() noexcept
346 {
347 return base::m_oDelegate;
348 }
349};
350
351template<typename T, typename StorageType>
352class object_ptr_delegate : public object_ptr_delegate_base<T, StorageType>
353{
354 static_assert(!::std::is_const_v<T> && !::std::is_same_v<T, IObject>);
355 using base = object_ptr_delegate_base<T, StorageType>;
356public:
357 using base::base;
358
359 constexpr operator const iobject_ptr<const T>&() const noexcept final override
360 {
361 return base::m_oDelegate;
362 }
363
364 constexpr operator const iobject_ptr<const IObject>&() const noexcept
365 {
366 return base::m_oDelegate;
367 }
368
369 constexpr operator const iobject_ptr<IObject>&() const noexcept
370 {
371 return base::m_oDelegate;
372 }
373
374 constexpr operator iobject_ptr<IObject>&() noexcept
375 {
376 return base::m_oDelegate;
377 }
378};
379
380} // namespace detail
381
382template<typename T>
383class object_ptr : public detail::object_ptr_base<T, T>
384{
385 using base = detail::object_ptr_base<T, T>;
386
387public:
388 using base::base;
389};
390
391} // namespace ant
392
394using ant::object_ptr;
395
396} // namespace ucom
397} // namespace adtf
398
399// specializing the swap function to enable best match for compiler
401namespace std
402{
403template<typename T>
404inline void swap(adtf::ucom::ant::object_ptr<T>& i_oLHS, adtf::ucom::ant::object_ptr<T>& i_oRHS) noexcept
405{
406 i_oLHS.Swap(i_oRHS);
407}
408} // namespace std
A_UTILS_NS::cResult tResult
For backwards compatibility and to bring latest version into scope.
Definition result.h:736
#define RETURN_ERROR_DESC(_code,...)
Same as RETURN_ERROR(_error) using a printf like parameter list for detailed error description.
Definition result.h:44
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
Definition result.h:29
#define RETURN_IF_THROWS(s)
if the expression throws an exception, returns a tResult containing the exception information.
Definition result.h:123
#define RETURN_ERROR(code)
Return specific error code, which requires the calling function's return type to be tResult.
Definition result.h:42
Definition object_intf.h:33
tResult Reset(const iobject_ptr< T > &oOther) noexcept final override
Reset this object_ptr<> with the content of another iobject_ptr<>
Definition object_ptr.h:230
T * operator->() const noexcept final override
Operator-> overload to treat object_ptr<> types like real pointers.
Definition object_ptr.h:210
T * Get() const final override
Get raw pointer to shared object.
Definition object_ptr.h:198
object_ptr_storage(const iobject_ptr< U > &i_oOther, StorageType *pSharedObject) noexcept
Aliasing constructor.
Definition object_ptr.h:83
Base object pointer to realize binary compatible reference counting in interface methods.
Definition object_ptr_intf.h:112
Definition object_ptr.h:384
Implementation of a weak pointer for usage with iobject_ptr and object_ptr.
Definition weak_object_ptr.h:34
void swap(cResult &i_oLHS, cResult &i_oRHS) noexcept
Definition result.h:505
Namespace for all internally used functionality implemented.
Definition class_info.h:17
Namespace for all functionality of the ADTF UCOM SDK provided since v3.0.
Definition test_runtime.h:14
InterfacePointerType ucom_cast(ObjectPointerType i_pObject) noexcept
Definition ucom_cast.h:157
constexpr const char * get_iid() noexcept
Definition adtf_iid.h:429
Namespace for the ADTF uCOM SDK.
Definition adtf_system.h:324
ant::IObject IObject
Alias always bringing the latest version of ant::IObject into scope.
Definition object_intf.h:109
ant::iobject_ptr< T > iobject_ptr
Alias always bringing the latest version of ant::iobject_ptr into scope.
Definition object_ptr_intf.h:437
Namespace for all functionality provided by ADTF and its SDKs.
Definition adtf_client_connector.h:14