ADTF  3.18.4
object_ptr_privates.h
Go to the documentation of this file.
1 
7 #ifndef _ADTF_UCOM_ANT_OBJECT_PTR_PRIVATES_IMPLEMENTATION_HEADER_
8 #define _ADTF_UCOM_ANT_OBJECT_PTR_PRIVATES_IMPLEMENTATION_HEADER_
9 
10 namespace adtf
11 {
12 namespace ucom
13 {
14 namespace ant
15 {
16 
17 //forward declare pointer types
18 template<typename>
19 class iobject_ptr;
20 template<typename>
21 class object_ptr;
22 template<typename>
23 class weak_object_ptr;
24 template<typename>
26 template<typename>
27 class object_ptr_const_conversion;
28 
29 //forward declare pointer casts
30 template<typename T, typename U>
31 object_ptr<T> ucom_object_ptr_cast(const iobject_ptr<U>& i_oOther);
32 
34 namespace detail
35 {
36 
37 template< typename >
38 class delegate_object_ptr;
39 
40 //intermediate for delegate_object_ptr
41 template<typename T, typename Enable = void>
42 class delegate_object_ptr_resetter;
43 
44 //intermediate for delegate_object_ptr
45 template<typename T>
46 class delegate_object_ptr_resetter<
47  T,
48  typename std::enable_if<std::is_class<T>::value && has_interface_info_type<typename std::remove_cv<T>::type>::value && std::is_same<typename std::remove_cv<T>::type, typename T::interface_type>::value>::type
49 > :
50  public object_ptr_const_conversion<typename iobject_ptr<T>::object_type>
51 {
52  typedef typename iobject_ptr<T>::object_type object_type;
53 
54 public: //implement Reset function with CRTP
55  virtual tResult Reset(const iobject_ptr<object_type>& i_oOther)
56  { //in case of an error, still reset!
57  using child_type = delegate_object_ptr<T>;
58  const auto pTmp = ucom_cast<T*>(i_oOther.Get());
59  if (pTmp)
60  {
61  static_cast<child_type&>(*this) = child_type(i_oOther.GetObjPtrRef(), pTmp);
62  }
63  else
64  {
65  static_cast<child_type&>(*this) = child_type();
66  }
67 
68  //successful if either reset pointer is not nil (ucom_cast succeeded)
69  //or incoming pointer is nil
70  const bool bSuccess = static_cast<child_type&>(*this).Get() || !i_oOther.Get();
71  if (!bSuccess)
72  {
73  RETURN_ERROR_DESC(ERR_NO_INTERFACE, "Object does not implement interface '%s'.", get_iid<T>());
74  }
75 
77  }
78 };//template<typename T> class delegate_object_ptr_resetter<T, true>
79 
80 template<typename T>
81 class delegate_object_ptr_resetter<
82  T,
83  typename std::enable_if<std::is_class<T>::value && has_interface_info_type<typename std::remove_cv<T>::type>::value && !std::is_same<typename std::remove_cv<T>::type, typename T::interface_type>::value>::type
84 > :
85  public object_ptr_const_conversion<typename iobject_ptr<T>::object_type>
86 {
87  typedef typename iobject_ptr<T>::object_type object_type;
88 
89 private:
90  virtual tResult Reset(const iobject_ptr<object_type>&)
91  { //implement private and empty, as there is no way to reset from IObject without IID defined
92  return ERR_NOT_IMPL;
93  }
94 };//template<typename T> class delegate_object_ptr_resetter<T, true>
95 
96 template<typename T>
97 class delegate_object_ptr_resetter<
98  T,
99  typename std::enable_if<!std::is_class<T>::value || !has_interface_info_type<typename std::remove_cv<T>::type>::value>::type
100 > :
101  public object_ptr_const_conversion<typename iobject_ptr<T>::object_type>
102 {
103  typedef typename iobject_ptr<T>::object_type object_type;
104 
105 private:
106  virtual tResult Reset(const iobject_ptr<object_type>&)
107  { //implement private and empty, as there is no way to reset from IObject without IID defined
108  return ERR_NOT_IMPL;
109  }
110 }; //template<typename T> class delegate_object_ptr_resetter<T, true>
111 
115 template<typename TSize>
116 class DOEXPORT iobject_ptr_ref
117 {
118  template<typename> friend class adtf::ucom::ant::weak_object_ptr;
119  template<typename> friend class delegate_object_ptr;
120 
121 protected: //types
122  typedef TSize size_type;
123 
124 protected: //construction/destruction
126  ~iobject_ptr_ref() = default;
127 
128 private:
129  virtual void IncreaseUseCount() = 0;
130  virtual void DecreaseUseCount() = 0;
131 
132  virtual void IncreaseWeakCount() = 0;
133  virtual void DecreaseWeakCount() = 0;
134 
135  virtual bool IncreaseUseCountNonZero() = 0;
136 };//class iobject_ptr_base
137 
138 //base class for the shared reference counter
139 class object_reference_counter : public iobject_ptr_ref<size_t>
140 {
141 public: //types
143  typedef iobject_ptr_ref<size_t>::size_type size_type;
144 
145 public:
146  template<typename U>
147  explicit object_reference_counter(U* pObjImpl) :
148  m_szUseCount(),
149  m_szWeakCount(1),
150  m_pObjImpl(ucom_cast<const IObject*>(pObjImpl))
151  {
152  }
153 
154  virtual ~object_reference_counter()
155  {
156  }
157 
158  virtual void IncreaseUseCount()
159  {
160  m_szUseCount++;
161  }
162 
163  virtual void DecreaseUseCount()
164  {
165  //if the use count is zero, delete the shared resource
166  if (0 == --m_szUseCount)
167  {
168  Destroy();
169  DecreaseWeakCount();
170  }
171  }
172 
173  virtual void IncreaseWeakCount()
174  {
175  m_szWeakCount++;
176  }
177 
178  virtual void DecreaseWeakCount()
179  {
180  //if the weak count is zero, delete the resource manager
181  if (0 == --m_szWeakCount)
182  {
183  delete this;
184  }
185  }
186 
187  virtual bool IncreaseUseCountNonZero()
188  {
189  size_type szExpected = m_szUseCount;
190  //Loop as long as either the use count got increased by one or the use count is 0
191  //This step is necessary to ensure the use count won't be zero between two non atomic
192  //operations
193  //Mind that szExpected is set to the current value by the compare and exchange method call.
194  while (0 != szExpected &&
195  !m_szUseCount.compare_exchange_weak(szExpected, szExpected + 1));
196 
197  return 0 != szExpected;
198  }
199 
200 private:
201  void Destroy() const
202  {
203  m_pObjImpl->Destroy();
204  }
205 
206 private: //types
207  std::atomic<size_type> m_szUseCount;
208  std::atomic<size_type> m_szWeakCount;
209  const IObject* const m_pObjImpl;
210 };//class object_reference_counter
211 
215 template<typename T>
216 class delegate_object_ptr : public delegate_object_ptr_resetter<T>
217 {
219  typedef typename iobject_ptr<T>::object_type object_type;
220 
221  template< typename > friend class adtf::ucom::ant::object_ptr;
222  template< typename, typename > friend class delegate_object_ptr_resetter;
223 
224  template<typename Implementation, typename ...Args> friend
225  typename std::enable_if
226  <
227  std::is_base_of
228  <
229  enable_object_ptr_from_this<typename std::remove_cv<Implementation>::type>,
230  typename std::remove_cv<Implementation>::type
231  >::value,
232  object_ptr<Implementation>
233  >::type
234  make_object_ptr(Args&&... args);
235 
236 private: //data section
238  typedef object_reference_counter::size_type size_type;
239 
240  iobject_ptr_ref<size_type>* m_pRefer;
241  T* m_pSharedObject;
242 
243 private: //member section
245  delegate_object_ptr() :
246  m_pRefer(nullptr),
247  m_pSharedObject(nullptr)
248  {
249  }
250 
252  delegate_object_ptr(iobject_ptr_ref<size_type>* pRefer, T* pObject)
253  : m_pRefer(pRefer), m_pSharedObject(pObject)
254  {
255  RefObject();
256  }
257 
258  delegate_object_ptr(const delegate_object_ptr& oOther)
259  : m_pRefer(oOther.m_pRefer),
260  m_pSharedObject(oOther.m_pSharedObject)
261  {
262  RefObject();
263  }
264 
265  delegate_object_ptr(delegate_object_ptr&& oOther)
266  {
267  Swap(oOther);
268  }
269 
270  template<typename U>
271  delegate_object_ptr(const weak_object_ptr<U>& i_pWeak) : delegate_object_ptr()
272  { //let's try to implement this thread safe...
273  if (nullptr != i_pWeak.m_pRefer && i_pWeak.m_pRefer->IncreaseUseCountNonZero())
274  {
275  m_pRefer = i_pWeak.m_pRefer;
276  m_pSharedObject = i_pWeak.m_pObject;
277  }
278  }
279 
280  delegate_object_ptr& operator= (delegate_object_ptr i_oOther)
281  {
282  Swap(i_oOther);
283  return *this;
284  }
285 
286  ~delegate_object_ptr()
287  {
288  UnrefObject();
289  }
290 
291  void RefObject()
292  {
293  if (nullptr != m_pRefer)
294  {
295  m_pRefer->IncreaseUseCount();
296  }
297  }
298 
299  void UnrefObject()
300  {
301  if (nullptr != m_pRefer)
302  {
303  m_pRefer->DecreaseUseCount();
304  m_pSharedObject = nullptr;
305  m_pRefer = nullptr;
306  }
307  }
308 
309  void Swap(delegate_object_ptr& o_oOther)
310  {
311  using std::swap;
312  swap(m_pRefer, o_oOther.m_pRefer);
313  swap(m_pSharedObject, o_oOther.m_pSharedObject);
314  }
315 
316 public: //implement iobject_ptr
317  virtual object_type* Get() const
318  {
319  return ucom_cast<object_type*>(m_pSharedObject);
320  }
321 
322  virtual object_type* operator->() const
323  {
324  return ucom_cast<object_type*>(m_pSharedObject);
325  }
326 
327 private: //implement iobject_ptr privates
328  virtual iobject_ptr_ref<size_type>* GetObjPtrRef() const
329  {
330  return m_pRefer;
331  }
332 };//end delegator
333 
334 }//ns detail
335 }//ns ant
336 }//ns ucom
337 }//ns adtf
338 
339 //specializing the swap function to enable best match for compiler
341 namespace std
342 {
343  template<typename T>
344  inline void swap(adtf::ucom::ant::detail::delegate_object_ptr<T>& i_oLHS,
345  adtf::ucom::ant::detail::delegate_object_ptr<T>& i_oRHS)
346  {
347  i_oLHS.Swap(i_oRHS);
348  }
349 }//ns std
351 
352 #endif //_ADTF_UCOM_ANT_OBJECT_PTR_PRIVATES_IMPLEMENTATION_HEADER_
#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.
IObject object_type
Provided for single point of const correct type access.
Object pointer implementation used for reference counting on objects of type IObject.
Definition: object_ptr.h:163
Implementation of a weak pointer for usage with iobject_ptr and object_ptr.
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
InterfacePointerType ucom_cast(ObjectPointerType i_pObject)
Used to cast arbitrary interface types within the UCOM.
Definition: ucom_cast.h:126
std::enable_if< !std::is_base_of< enable_object_ptr_from_this< typename std::remove_cv< Implementation >::type >, typename std::remove_cv< Implementation >::type >::value, object_ptr< Implementation > >::type make_object_ptr(Args &&... args)
Create an instance of type object_ptr with Implementation as the shared resource.
object_ptr< T > ucom_object_ptr_cast(const iobject_ptr< U > &i_oOther)
Create an object_ptr with an already shared resource of implicitly convertible type.
ant::weak_object_ptr< T > weak_object_ptr
Alias always bringing the latest version of ant::weak_object_ptr into scope.
ant::object_ptr< T > object_ptr
Alias always bringing the latest version of ant::object_ptr into scope.
Definition: object_ptr.h:413
ant::iobject_ptr< T > iobject_ptr
Alias always bringing the latest version of ant::iobject_ptr into scope.
ant::enable_object_ptr_from_this< T > enable_object_ptr_from_this
Alias always bringing the latest version of ant::enable_object_ptr_from_this into scope.
ant::IObject IObject
Alias always bringing the latest version of ant::IObject into scope.
Definition: object_intf.h:102
Namespace for entire ADTF SDK.