Merge "Include the algorithm header file" into devel/master
[platform/core/uifw/dali-core.git] / dali / public-api / common / intrusive-ptr.h
1 #ifndef DALI_INTRUSIVE_PTR_H
2 #define DALI_INTRUSIVE_PTR_H
3
4 /*
5  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23
24 namespace Dali
25 {
26 /**
27  * @addtogroup dali_core_common
28  * @{
29  */
30
31 /**
32  * @brief Templated intrusive pointer class.
33  *
34  * Uses the Dali:RefObject type with actual reference counting.
35  * The object is responsible for destroying itself.
36  * @SINCE_1_0.0
37  */
38 template<typename T>
39 class IntrusivePtr
40 {
41 public:
42   /**
43    * @brief Standard constructor to unassigned object.
44    * @SINCE_1_0.0
45    */
46   IntrusivePtr()
47   : mPtr(nullptr)
48   {
49   }
50
51   /**
52    * @brief Constructor to attach existing object.
53    *
54    * @SINCE_1_0.0
55    * @param[in] p Pointer to object
56    */
57   IntrusivePtr(T* p)
58   : mPtr(p)
59   {
60     if(mPtr)
61     {
62       mPtr->Reference();
63     }
64   }
65
66   /**
67    * @brief Copy constructor.
68    *
69    * @SINCE_1_0.0
70    * @param[in] rhs Const reference to an IntrusivePtr
71    * @tparam U Reference counter object type
72    */
73   template<typename U>
74   IntrusivePtr(IntrusivePtr<U> const& rhs)
75   : mPtr(rhs.Get())
76   {
77     if(mPtr)
78     {
79       mPtr->Reference();
80     }
81   }
82
83   /**
84    * @brief Copy constructor.
85    * @SINCE_1_0.0
86    * @param[in] rhs Const reference to an IntrusivePtr
87    */
88   IntrusivePtr(IntrusivePtr const& rhs)
89   : mPtr(rhs.mPtr)
90   {
91     if(mPtr)
92     {
93       mPtr->Reference();
94     }
95   }
96
97   /**
98    * @brief Move constructor.
99    * @SINCE_1_9.23
100    * @param[in] rhs Reference to an IntrusivePtr
101    */
102   template<typename U>
103   IntrusivePtr(IntrusivePtr<U>&& rhs)
104   : mPtr(rhs.Detach())
105   {
106   }
107
108   /**
109    * @brief Move constructor.
110    * @SINCE_1_9.23
111    * @param[in] rhs Reference to an IntrusivePtr
112    */
113   IntrusivePtr(IntrusivePtr&& rhs)
114   : mPtr(rhs.Detach())
115   {
116   }
117
118   /**
119    * @brief Destructor.
120    *
121    * Object will self-destruct if reference count is zero.
122    * @SINCE_1_0.0
123    */
124   ~IntrusivePtr()
125   {
126     if(mPtr)
127     {
128       mPtr->Unreference();
129     }
130   }
131
132   /**
133    * @brief Gets pointer to reference counted object.
134    *
135    * @SINCE_1_0.0
136    * @return Pointer to reference counted object
137    */
138   T* Get() const
139   {
140     return mPtr;
141   }
142
143   /**
144    * @brief Pointer operator override.
145    *
146    * @SINCE_1_0.0
147    * @return Pointer to reference counted object
148    */
149   T* operator->() const
150   {
151     return mPtr;
152   }
153
154   /**
155    * @brief Dereference operator override.
156    *
157    * @SINCE_1_0.0
158    * @return Reference to reference counted object
159    */
160   T& operator*() const
161   {
162     return *mPtr;
163   }
164
165   /**
166    * @brief Assignment operator.
167    *
168    * @SINCE_1_0.0
169    * @param rhs Const reference to intrusive pointer
170    * @return Reference to reference counted object
171    */
172   IntrusivePtr& operator=(IntrusivePtr const& rhs)
173   {
174     IntrusivePtr(rhs).Swap(*this);
175     return *this;
176   }
177
178   /**
179    * @brief Assignment operator.
180    *
181    * @SINCE_1_0.0
182    * @param rhs Pointer to object to wrap
183    * @return A Reference to this object
184    */
185   IntrusivePtr& operator=(T* rhs)
186   {
187     IntrusivePtr(rhs).Swap(*this);
188     return *this;
189   }
190
191   /**
192    * @brief Move assignment operator.
193    *
194    * @SINCE_1_9.23
195    * @param rhs Reference to intrusive pointer
196    * @return Reference to moved intrusive pointer
197    */
198   IntrusivePtr& operator=(IntrusivePtr&& rhs)
199   {
200     if(this != &rhs)
201     {
202       if(mPtr)
203       {
204         mPtr->Unreference();
205       }
206       mPtr = rhs.Detach();
207     }
208
209     return *this;
210   }
211
212   /**
213    * @brief Move assignment operator.
214    *
215    * @SINCE_1_9.23
216    * @param rhs Reference to intrusive pointer
217    * @return Reference to moved intrusive pointer
218    */
219   template<typename U>
220   IntrusivePtr& operator=(IntrusivePtr<U>&& rhs)
221   {
222     if(this != reinterpret_cast<IntrusivePtr<T>*>(&rhs))
223     {
224       if(mPtr)
225       {
226         mPtr->Unreference();
227       }
228       mPtr = rhs.Detach();
229     }
230
231     return *this;
232   }
233
234   /**
235    * @brief Reset intrusive pointer.
236    * @SINCE_1_0.0
237    */
238   void Reset()
239   {
240     IntrusivePtr().Swap(*this);
241   }
242
243   /**
244    * @brief Reset intrusive pointer with reference counted object.
245    *
246    * @SINCE_1_0.0
247    * @param[in] rhs Pointer to object
248    */
249   void Reset(T* rhs)
250   {
251     IntrusivePtr(rhs).Swap(*this);
252   }
253
254   // IntrusivePtr comparisons - This is a variation of the safe bool idiom
255
256   /**
257    * @brief Pointer-to-member type.
258    *
259    * Objects can be implicitly converted to this for validity checks.
260    */
261   using BooleanType = void (IntrusivePtr<T>::*)() const;
262
263   /**
264    * @brief Converts an object handle to a BooleanType.
265    *
266    * This is useful for checking whether the handle is NULL.
267    * @SINCE_1_0.0
268    */
269   operator BooleanType() const
270   {
271     return mPtr ? &IntrusivePtr::ThisIsSaferThanReturningVoidStar : nullptr;
272   }
273
274   /**
275    * @brief Detaches pointer from intrusive ptr counting.
276    *
277    * Use with care.
278    * @SINCE_1_0.0
279    * @return Pointer to reference counted object
280    */
281   T* Detach()
282   {
283     T* ptr = mPtr;
284     mPtr   = nullptr;
285     return ptr;
286   }
287
288 private:
289   /**
290    * @brief Used by the safe bool idiom.
291    * @SINCE_1_0.0
292    */
293   void ThisIsSaferThanReturningVoidStar() const
294   {
295   }
296
297   /**
298    * @brief Internal swap function.
299    * @SINCE_1_0.0
300    */
301   void Swap(IntrusivePtr& rhs)
302   {
303     T* tmp   = mPtr;
304     mPtr     = rhs.mPtr;
305     rhs.mPtr = tmp;
306   }
307
308   T* mPtr; ///< pointer to RefObject
309 };
310
311 /**
312  * @brief Comparison overrides of objects wrapped by intrusive pointers.
313  *
314  * @SINCE_1_0.0
315  * @param[in] lhs Intrusive pointer to compare with
316  * @param[in] rhs Intrusive pointer to compare against
317  * @return True if the pointers point at the same object
318  */
319 template<typename T, typename U>
320 inline bool operator==(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
321 {
322   return lhs.Get() == rhs.Get();
323 }
324
325 /**
326  * @brief Comparison overrides of objects wrapped by intrusive pointers.
327  *
328  * @SINCE_1_0.0
329  * @param[in] lhs Intrusive pointer to compare with
330  * @param[in] rhs Intrusive pointer to compare against
331  * @return True if the pointers point at different objects
332  */
333 template<typename T, typename U>
334 inline bool operator!=(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
335 {
336   return lhs.Get() != rhs.Get();
337 }
338
339 /**
340  * @brief Comparison overrides of objects wrapped by intrusive pointers.
341  *
342  * @SINCE_1_0.0
343  * @param[in] lhs Intrusive pointer to compare with
344  * @param[in] rhs Object to compare against
345  * @return True if the intrusive pointer points at the specified object
346  */
347 template<typename T, typename U>
348 inline bool operator==(IntrusivePtr<T> const& lhs, U* rhs)
349 {
350   return lhs.Get() == rhs;
351 }
352
353 /**
354  * @brief Comparison overrides of objects wrapped by intrusive pointers.
355  *
356  * @SINCE_1_0.0
357  * @param[in] lhs Intrusive pointer to compare with
358  * @param[in] rhs Intrusive pointer to compare against
359  * @return True if the intrusive pointer doesn't point at the specified object
360  */
361 template<typename T, typename U>
362 inline bool operator!=(IntrusivePtr<T> const& lhs, U* rhs)
363 {
364   return lhs.Get() != rhs;
365 }
366
367 /**
368  * @brief Comparison overrides of objects wrapped by intrusive pointers.
369  *
370  * @SINCE_1_0.0
371  * @param[in] lhs Object to compare with
372  * @param[in] rhs Intrusive pointer to compare against
373  * @return True if the intrusive pointer points at the specified object
374  */
375 template<typename T, typename U>
376 inline bool operator==(T* lhs, IntrusivePtr<U> const& rhs)
377 {
378   return lhs == rhs.Get();
379 }
380
381 /**
382  * @brief Comparison overrides of objects wrapped by intrusive pointers.
383  *
384  * @SINCE_1_0.0
385  * @param[in] lhs Object to compare with
386  * @param[in] rhs Intrusive pointer to compare against
387  * @return True if the intrusive pointer doesn't point at the specified object
388  */
389 template<typename T, typename U>
390 inline bool operator!=(T* lhs, IntrusivePtr<U> const& rhs)
391 {
392   return lhs != rhs.Get();
393 }
394
395 /**
396  * @}
397  */
398 } // namespace Dali
399
400 #endif // DALI_INTRUSIVE_PTR_H