ADTF
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 else if constexpr (::std::is_same_v<std::remove_const_t<T>, IObject> &&
245 ::std::is_const_v<StorageType> == ::std::is_const_v<T> &&
246 has_interface_info_type<::std::remove_const_t<StorageType>>::value)
247 {
248 const auto pObject = ucom_cast<StorageType*>(oOther.Get());
249 if (!pObject)
250 {
251 RETURN_ERROR_DESC(ERR_NO_INTERFACE, "Object does not implement interface '%s'.",
253 }
254
255 object_ptr_base<T, StorageType> oHelper(oOther, pObject);
256 Swap(oHelper);
258 }
259 else
260 {
261 RETURN_ERROR(ERR_NO_INTERFACE);
262 }
263 }
264
265 object_ptr_delegate_base& operator=(const object_ptr_delegate_base& oOther)
266 {
267 m_oDelegate = oOther.m_oDelegate;
268 return *this;
269 }
270
271 object_ptr_delegate_base& operator=(object_ptr_delegate_base&& oOther)
272 {
273 m_oDelegate = ::std::move(oOther.m_oDelegate);
274 return *this;
275 }
276
277 constexpr explicit operator bool() const noexcept
278 {
279 return (GetStorageObject() != nullptr);
280 }
281
282protected:
283 ::std::conditional_t<::std::is_same_v<std::remove_const_t<T>, IObject>,
284 std::conditional_t<!::std::is_const_v<T> && !::std::is_const_v<StorageType>,
285 object_ptr_const_iobject_delegate<StorageType>,
286 object_ptr_storage<StorageType>>,
287 std::conditional_t<::std::is_const_v<T> || ::std::is_const_v<StorageType>,
288 ::std::conditional_t<::std::is_const_v<StorageType>,
289 object_ptr_const_iobject_delegate<StorageType>,
290 object_ptr_iobject_delegate<StorageType>>,
291 object_ptr_const_delegate<const T, StorageType>>>
292 m_oDelegate;
293};
294
295template<typename StorageType>
296class object_ptr_const_iobject_delegate : public object_ptr_delegate_base<const IObject, StorageType>
297{
298public:
299 using object_ptr_delegate_base<const IObject, StorageType>::object_ptr_delegate_base;
300};
301
302template<typename StorageType>
303class object_ptr_iobject_delegate : public object_ptr_delegate_base<IObject, StorageType>
304{
305 using base = object_ptr_delegate_base<IObject, StorageType>;
306public:
307 using base::base;
308
309 constexpr operator const iobject_ptr<const IObject>&() const noexcept final override
310 {
311 return base::m_oDelegate;
312 }
313};
314
315template<typename T, typename StorageType>
316class object_ptr_const_delegate : public object_ptr_delegate_base<T, StorageType>
317{
318 static_assert(::std::is_const_v<T> && !::std::is_same_v<T, const IObject>);
319
320 using base = object_ptr_delegate_base<T, StorageType>;
321public:
322 using base::base;
323
324 constexpr operator const iobject_ptr<const IObject>&() const noexcept
325 {
326 return base::m_oDelegate;
327 }
328
329 template<typename U, typename = ::std::enable_if_t<::std::is_same_v<U, IObject> && !::std::is_const_v<StorageType>>>
330 constexpr operator const iobject_ptr<U>&() const noexcept
331 {
332 return base::m_oDelegate;
333 }
334
335 template<typename U,
336 typename = std::enable_if_t<(::std::is_same_v<U, const IObject> && ::std::is_const_v<StorageType>) ||
337 (::std::is_same_v<U, IObject> && !::std::is_const_v<StorageType>)>>
338 constexpr operator iobject_ptr<U>&() noexcept
339 {
340 return base::m_oDelegate;
341 }
342};
343
344template<typename T, typename StorageType>
345class object_ptr_delegate : public object_ptr_delegate_base<T, StorageType>
346{
347 static_assert(!::std::is_const_v<T> && !::std::is_same_v<T, IObject>);
348 using base = object_ptr_delegate_base<T, StorageType>;
349public:
350 using base::base;
351
352 constexpr operator const iobject_ptr<const T>&() const noexcept final override
353 {
354 return base::m_oDelegate;
355 }
356
357 constexpr operator const iobject_ptr<const IObject>&() const noexcept
358 {
359 return base::m_oDelegate;
360 }
361
362 constexpr operator const iobject_ptr<IObject>&() const noexcept
363 {
364 return base::m_oDelegate;
365 }
366
367 constexpr operator iobject_ptr<IObject>&() noexcept
368 {
369 return base::m_oDelegate;
370 }
371};
372
373} // namespace detail
374
375template<typename T>
376class object_ptr : public detail::object_ptr_base<T, T>
377{
378 using base = detail::object_ptr_base<T, T>;
379
380public:
381 using base::base;
382};
383
384} // namespace ant
385
387using ant::object_ptr;
388
389} // namespace ucom
390} // namespace adtf
391
392// specializing the swap function to enable best match for compiler
394namespace std
395{
396template<typename T>
397inline void swap(adtf::ucom::ant::object_ptr<T>& i_oLHS, adtf::ucom::ant::object_ptr<T>& i_oRHS) noexcept
398{
399 i_oLHS.Swap(i_oRHS);
400}
401} // namespace std
A_UTILS_NS::cResult tResult
For backwards compatibility and to bring latest version into scope.
#define RETURN_ERROR_DESC(_code,...)
Same as RETURN_ERROR(_error) using a printf like parameter list for detailed error description.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.
#define RETURN_ERROR(code)
Return specific error code, which requires the calling function's return type to be tResult.
Base class for every interface type within the uCOM.
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
detail::iobject_ptr_ref< size_t > * m_pRefer
Refer to control the weak counting.
Definition object_ptr.h:140
object_ptr_storage(const iobject_ptr< U > &i_oOther, StorageType *pSharedObject) noexcept
Aliasing constructor.
Definition object_ptr.h:83
StorageType * m_pObject
The managed object.
Definition object_ptr.h:139
Base object pointer to realize binary compatible reference counting in interface methods.
Implementation of a weak pointer for usage with iobject_ptr and object_ptr.
T * m_pObject
The managed object.
detail::iobject_ptr_ref< size_type > * m_pRefer
Refer to control the weak counting.
tVoid swap(A_UTILS_NS::d_ptr< _PARENT, _PRIVATE_D > &i_oLHS, A_UTILS_NS::d_ptr< _PARENT, _PRIVATE_D > &i_oRHS)
std::swap specialization for AUTILSDPtr for perfect fit on ADL
Definition d_ptr.h:237
Namespace for all internally used uCOM functionality implemented.
Namespace for all functionality provided since v3.0.
const char * get_iid()
Get the interface id (IID) of the Interface type.
Definition adtf_iid.h:434
InterfacePointerType ucom_cast(ObjectPointerType i_pObject)
Used to cast arbitrary interface types within the UCOM.
Definition ucom_cast.h:126
Namespace for the ADTF uCOM3 SDK.
ant::iobject_ptr< T > iobject_ptr
Alias always bringing the latest version of ant::iobject_ptr into scope.
ant::IObject IObject
Alias always bringing the latest version of ant::IObject into scope.
Namespace for entire ADTF SDK.
Copyright © Audi Electronics Venture GmbH.
#define RETURN_IF_THROWS(s)
if the expression throws an exception, returns a tResult containing the exception information.