Make Dali::InstrusivePtr able to compare with nullptr
[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) 2022 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 // EXTERNAL INCLUDES
22 #include <cstddef> // for std::nullptr_t
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26
27 namespace Dali
28 {
29 /**
30  * @addtogroup dali_core_common
31  * @{
32  */
33
34 /**
35  * @brief Templated intrusive pointer class.
36  *
37  * Uses the Dali:RefObject type with actual reference counting.
38  * The object is responsible for destroying itself.
39  * @SINCE_1_0.0
40  */
41 template<typename T>
42 class IntrusivePtr
43 {
44 public:
45   /**
46    * @brief Standard constructor to unassigned object.
47    * @SINCE_1_0.0
48    */
49   IntrusivePtr()
50   : mPtr(nullptr)
51   {
52   }
53
54   /**
55    * @brief Constructor to attach existing object.
56    *
57    * @SINCE_1_0.0
58    * @param[in] p Pointer to object
59    */
60   IntrusivePtr(T* p)
61   : mPtr(p)
62   {
63     if(mPtr)
64     {
65       mPtr->Reference();
66     }
67   }
68
69   /**
70    * @brief Copy constructor.
71    *
72    * @SINCE_1_0.0
73    * @param[in] rhs Const reference to an IntrusivePtr
74    * @tparam U Reference counter object type
75    */
76   template<typename U>
77   IntrusivePtr(IntrusivePtr<U> const& rhs)
78   : mPtr(rhs.Get())
79   {
80     if(mPtr)
81     {
82       mPtr->Reference();
83     }
84   }
85
86   /**
87    * @brief Copy constructor.
88    * @SINCE_1_0.0
89    * @param[in] rhs Const reference to an IntrusivePtr
90    */
91   IntrusivePtr(IntrusivePtr const& rhs)
92   : mPtr(rhs.mPtr)
93   {
94     if(mPtr)
95     {
96       mPtr->Reference();
97     }
98   }
99
100   /**
101    * @brief Move constructor.
102    * @SINCE_1_9.23
103    * @param[in] rhs Reference to an IntrusivePtr
104    */
105   template<typename U>
106   IntrusivePtr(IntrusivePtr<U>&& rhs)
107   : mPtr(rhs.Detach())
108   {
109   }
110
111   /**
112    * @brief Move constructor.
113    * @SINCE_1_9.23
114    * @param[in] rhs Reference to an IntrusivePtr
115    */
116   IntrusivePtr(IntrusivePtr&& rhs)
117   : mPtr(rhs.Detach())
118   {
119   }
120
121   /**
122    * @brief Destructor.
123    *
124    * Object will self-destruct if reference count is zero.
125    * @SINCE_1_0.0
126    */
127   ~IntrusivePtr()
128   {
129     if(mPtr)
130     {
131       mPtr->Unreference();
132     }
133   }
134
135   /**
136    * @brief Gets pointer to reference counted object.
137    *
138    * @SINCE_1_0.0
139    * @return Pointer to reference counted object
140    */
141   T* Get() const
142   {
143     return mPtr;
144   }
145
146   /**
147    * @brief Pointer operator override.
148    *
149    * @SINCE_1_0.0
150    * @return Pointer to reference counted object
151    */
152   T* operator->() const
153   {
154     return mPtr;
155   }
156
157   /**
158    * @brief Dereference operator override.
159    *
160    * @SINCE_1_0.0
161    * @return Reference to reference counted object
162    */
163   T& operator*() const
164   {
165     return *mPtr;
166   }
167
168   /**
169    * @brief Assignment operator.
170    *
171    * @SINCE_1_0.0
172    * @param rhs Const reference to intrusive pointer
173    * @return Reference to reference counted object
174    */
175   IntrusivePtr& operator=(IntrusivePtr const& rhs)
176   {
177     IntrusivePtr(rhs).Swap(*this);
178     return *this;
179   }
180
181   /**
182    * @brief Assignment operator.
183    *
184    * @SINCE_1_0.0
185    * @param rhs Pointer to object to wrap
186    * @return A Reference to this object
187    */
188   IntrusivePtr& operator=(T* rhs)
189   {
190     IntrusivePtr(rhs).Swap(*this);
191     return *this;
192   }
193
194   /**
195    * @brief Move assignment operator.
196    *
197    * @SINCE_1_9.23
198    * @param rhs Reference to intrusive pointer
199    * @return Reference to moved intrusive pointer
200    */
201   IntrusivePtr& operator=(IntrusivePtr&& rhs)
202   {
203     if(this != &rhs)
204     {
205       if(mPtr)
206       {
207         mPtr->Unreference();
208       }
209       mPtr = rhs.Detach();
210     }
211
212     return *this;
213   }
214
215   /**
216    * @brief Move assignment operator.
217    *
218    * @SINCE_1_9.23
219    * @param rhs Reference to intrusive pointer
220    * @return Reference to moved intrusive pointer
221    */
222   template<typename U>
223   IntrusivePtr& operator=(IntrusivePtr<U>&& rhs)
224   {
225     if(this != reinterpret_cast<IntrusivePtr<T>*>(&rhs))
226     {
227       if(mPtr)
228       {
229         mPtr->Unreference();
230       }
231       mPtr = rhs.Detach();
232     }
233
234     return *this;
235   }
236
237   /**
238    * @brief Reset intrusive pointer.
239    * @SINCE_1_0.0
240    */
241   void Reset()
242   {
243     IntrusivePtr().Swap(*this);
244   }
245
246   /**
247    * @brief Reset intrusive pointer with reference counted object.
248    *
249    * @SINCE_1_0.0
250    * @param[in] rhs Pointer to object
251    */
252   void Reset(T* rhs)
253   {
254     IntrusivePtr(rhs).Swap(*this);
255   }
256
257   // IntrusivePtr comparisons
258
259   /**
260    * @brief Converts an object handle to a bool.
261    *
262    * This is useful for checking whether the handle is NULL.
263    * @SINCE_1_0.0
264    */
265   explicit operator bool() const
266   {
267     return mPtr != nullptr;
268   }
269
270   /**
271    * @brief Detaches pointer from intrusive ptr counting.
272    *
273    * Use with care.
274    * @SINCE_1_0.0
275    * @return Pointer to reference counted object
276    */
277   T* Detach()
278   {
279     T* ptr = mPtr;
280     mPtr   = nullptr;
281     return ptr;
282   }
283
284 private:
285   /**
286    * @brief Internal swap function.
287    * @SINCE_1_0.0
288    */
289   void Swap(IntrusivePtr& rhs)
290   {
291     T* tmp   = mPtr;
292     mPtr     = rhs.mPtr;
293     rhs.mPtr = tmp;
294   }
295
296   T* mPtr; ///< pointer to RefObject
297 };
298
299 /**
300  * @brief Comparison overrides of objects wrapped by intrusive pointers.
301  *
302  * @SINCE_1_0.0
303  * @param[in] lhs Intrusive pointer to compare with
304  * @param[in] rhs Intrusive pointer to compare against
305  * @return True if the pointers point at the same object
306  */
307 template<typename T, typename U>
308 inline bool operator==(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
309 {
310   return lhs.Get() == rhs.Get();
311 }
312
313 /**
314  * @brief Comparison overrides of objects wrapped by intrusive pointers.
315  *
316  * @SINCE_1_0.0
317  * @param[in] lhs Intrusive pointer to compare with
318  * @param[in] rhs Intrusive pointer to compare against
319  * @return True if the pointers point at different objects
320  */
321 template<typename T, typename U>
322 inline bool operator!=(IntrusivePtr<T> const& lhs, IntrusivePtr<U> const& rhs)
323 {
324   return lhs.Get() != rhs.Get();
325 }
326
327 /**
328  * @brief Comparison overrides of objects wrapped by intrusive pointers.
329  *
330  * @SINCE_1_0.0
331  * @param[in] lhs Intrusive pointer to compare with
332  * @param[in] rhs Object to compare against
333  * @return True if the intrusive pointer points at the specified object
334  */
335 template<typename T, typename U>
336 inline bool operator==(IntrusivePtr<T> const& lhs, U* rhs)
337 {
338   return lhs.Get() == rhs;
339 }
340
341 /**
342  * @brief Comparison overrides of objects wrapped by intrusive pointers.
343  *
344  * @SINCE_1_0.0
345  * @param[in] lhs Intrusive pointer to compare with
346  * @param[in] rhs Intrusive pointer to compare against
347  * @return True if the intrusive pointer doesn't point at the specified object
348  */
349 template<typename T, typename U>
350 inline bool operator!=(IntrusivePtr<T> const& lhs, U* rhs)
351 {
352   return lhs.Get() != rhs;
353 }
354
355 /**
356  * @brief Comparison overrides of objects wrapped by intrusive pointers.
357  *
358  * @SINCE_1_0.0
359  * @param[in] lhs Object to compare with
360  * @param[in] rhs Intrusive pointer to compare against
361  * @return True if the intrusive pointer points at the specified object
362  */
363 template<typename T, typename U>
364 inline bool operator==(T* lhs, IntrusivePtr<U> const& rhs)
365 {
366   return lhs == rhs.Get();
367 }
368
369 /**
370  * @brief Comparison overrides of objects wrapped by intrusive pointers.
371  *
372  * @SINCE_1_0.0
373  * @param[in] lhs Object to compare with
374  * @param[in] rhs Intrusive pointer to compare against
375  * @return True if the intrusive pointer doesn't point at the specified object
376  */
377 template<typename T, typename U>
378 inline bool operator!=(T* lhs, IntrusivePtr<U> const& rhs)
379 {
380   return lhs != rhs.Get();
381 }
382
383 /**
384  * @brief Comparison overrides of objects with nullptr_t.
385  *
386  * @SINCE_2_1.12
387  * @param[in] lhs Intrusive pointer to compare with
388  * @param[in] rhs nullptr
389  * @return True if the pointers is nullptr
390  */
391 template<typename T>
392 inline bool operator==(IntrusivePtr<T> const& lhs, std::nullptr_t rhs)
393 {
394   return lhs.Get() == nullptr;
395 }
396
397 /**
398  * @brief Comparison overrides of objects with nullptr_t.
399  *
400  * @SINCE_2_1.12
401  * @param[in] lhs Intrusive pointer to compare with
402  * @param[in] rhs nullptr
403  * @return True if the pointers is not nullptr
404  */
405 template<typename T>
406 inline bool operator!=(IntrusivePtr<T> const& lhs, std::nullptr_t rhs)
407 {
408   return lhs.Get() != nullptr;
409 }
410
411 /**
412  * @brief Comparison overrides of objects with nullptr_t.
413  *
414  * @SINCE_2_1.12
415  * @param[in] lhs nullptr
416  * @param[in] rhs Intrusive pointer to compare against
417  * @return True if the pointers is nullptr
418  */
419 template<typename T>
420 inline bool operator==(std::nullptr_t lhs, IntrusivePtr<T> const& rhs)
421 {
422   return nullptr == rhs.Get();
423 }
424
425 /**
426  * @brief Comparison overrides of objects with nullptr_t.
427  *
428  * @SINCE_2_1.12
429  * @param[in] lhs nullptr
430  * @param[in] rhs Intrusive pointer to compare against
431  * @return True if the pointers is not nullptr
432  */
433 template<typename T>
434 inline bool operator!=(std::nullptr_t lhs, IntrusivePtr<T> const& rhs)
435 {
436   return nullptr != rhs.Get();
437 }
438
439 /**
440  * @}
441  */
442 } // namespace Dali
443
444 #endif // DALI_INTRUSIVE_PTR_H