873a9985142ed099ed57a3c529480cb97a0aae6a
[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
42 public:
43
44   /**
45    * @brief Standard constructor to unassigned object.
46    * @SINCE_1_0.0
47    */
48   IntrusivePtr() : mPtr( 0 ) {}
49
50   /**
51    * @brief Constructor to attach existing object.
52    *
53    * @SINCE_1_0.0
54    * @param[in] p Pointer to object
55    */
56   IntrusivePtr( T* p ) : mPtr( p )
57   {
58     if( mPtr )
59     {
60       mPtr->Reference();
61     }
62   }
63
64   /**
65    * @brief Copy constructor.
66    *
67    * @SINCE_1_0.0
68    * @param[in] rhs Const reference to an IntrusivePtr
69    * @tparam U Reference counter object type
70    */
71   template<typename U>
72   IntrusivePtr( IntrusivePtr<U> const& rhs ) : mPtr( rhs.Get() )
73   {
74     if( mPtr )
75     {
76       mPtr->Reference();
77     }
78   }
79
80   /**
81    * @brief Copy constructor.
82    * @SINCE_1_0.0
83    * @param[in] rhs Const reference to an IntrusivePtr
84    */
85   IntrusivePtr( IntrusivePtr const& rhs ) : mPtr( rhs.mPtr )
86   {
87     if( mPtr )
88     {
89       mPtr->Reference();
90     }
91   }
92
93   /**
94    * @brief Move constructor.
95    * @SINCE_1_9.23
96    * @param[in] rhs Reference to an IntrusivePtr
97    */
98   template<typename U>
99   IntrusivePtr( IntrusivePtr<U>&& rhs )
100   : mPtr( rhs.Detach() )
101   {
102   }
103
104   /**
105    * @brief Move constructor.
106    * @SINCE_1_9.23
107    * @param[in] rhs Reference to an IntrusivePtr
108    */
109   IntrusivePtr( IntrusivePtr&& rhs )
110   : mPtr( rhs.Detach() )
111   {
112   }
113
114   /**
115    * @brief Destructor.
116    *
117    * Object will self-destruct if reference count is zero.
118    * @SINCE_1_0.0
119    */
120   ~IntrusivePtr()
121   {
122     if( mPtr )
123     {
124       mPtr->Unreference();
125     }
126   }
127
128   /**
129    * @brief Gets pointer to reference counted object.
130    *
131    * @SINCE_1_0.0
132    * @return Pointer to reference counted object
133    */
134   T* Get() const
135   {
136     return mPtr;
137   }
138
139   /**
140    * @brief Pointer operator override.
141    *
142    * @SINCE_1_0.0
143    * @return Pointer to reference counted object
144    */
145   T* operator->() const
146   {
147     return mPtr;
148   }
149
150   /**
151    * @brief Dereference operator override.
152    *
153    * @SINCE_1_0.0
154    * @return Reference to reference counted object
155    */
156   T& operator*() const
157   {
158     return *mPtr;
159   }
160
161   /**
162    * @brief Assignment operator.
163    *
164    * @SINCE_1_0.0
165    * @param rhs Const reference to intrusive pointer
166    * @return Reference to reference counted object
167    */
168   IntrusivePtr& operator=( IntrusivePtr const& rhs )
169   {
170     IntrusivePtr( rhs ).Swap( *this );
171     return *this;
172   }
173
174   /**
175    * @brief Assignment operator.
176    *
177    * @SINCE_1_0.0
178    * @param rhs Pointer to object to wrap
179    * @return A Reference to this object
180    */
181   IntrusivePtr& operator=( T* rhs )
182   {
183     IntrusivePtr( rhs ).Swap( *this );
184     return *this;
185   }
186
187   /**
188    * @brief Move assignment operator.
189    *
190    * @SINCE_1_9.23
191    * @param rhs Reference to intrusive pointer
192    * @return Reference to moved intrusive pointer
193    */
194   IntrusivePtr& operator=( IntrusivePtr&& rhs )
195   {
196     if ( this != &rhs )
197     {
198       if (mPtr)
199       {
200         mPtr->Unreference();
201       }
202       mPtr = rhs.Detach();
203     }
204
205     return *this;
206   }
207
208   /**
209    * @brief Move assignment operator.
210    *
211    * @SINCE_1_9.23
212    * @param rhs Reference to intrusive pointer
213    * @return Reference to moved intrusive pointer
214    */
215   template<typename U>
216   IntrusivePtr& operator=( IntrusivePtr<U>&& rhs )
217   {
218     if ( this != reinterpret_cast<IntrusivePtr<T>*>( &rhs ) )
219     {
220       if (mPtr)
221       {
222         mPtr->Unreference();
223       }
224       mPtr = rhs.Detach();
225     }
226
227     return *this;
228   }
229
230   /**
231    * @brief Reset intrusive pointer.
232    * @SINCE_1_0.0
233    */
234   void Reset()
235   {
236     IntrusivePtr().Swap( *this );
237   }
238
239   /**
240    * @brief Reset intrusive pointer with reference counted object.
241    *
242    * @SINCE_1_0.0
243    * @param[in] rhs Pointer to object
244    */
245   void Reset( T* rhs )
246   {
247     IntrusivePtr( rhs ).Swap( *this );
248   }
249
250   // IntrusivePtr comparisons - This is a variation of the safe bool idiom
251
252   /**
253    * @brief Pointer-to-member type.
254    *
255    * Objects can be implicitly converted to this for validity checks.
256    */
257   typedef void (IntrusivePtr::*BooleanType)() const;
258
259   /**
260    * @brief Converts an object handle to a BooleanType.
261    *
262    * This is useful for checking whether the handle is NULL.
263    * @SINCE_1_0.0
264    */
265   operator BooleanType() const
266   {
267     return mPtr ? &IntrusivePtr::ThisIsSaferThanReturningVoidStar : 0;
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 = 0;
281     return ptr;
282   }
283
284 private:
285
286   /**
287    * @brief Used by the safe bool idiom.
288    * @SINCE_1_0.0
289    */
290   void ThisIsSaferThanReturningVoidStar() const {}
291
292   /**
293    * @brief Internal swap function.
294    * @SINCE_1_0.0
295    */
296   void Swap( IntrusivePtr& rhs )
297   {
298     T* tmp = mPtr;
299     mPtr = rhs.mPtr;
300     rhs.mPtr = tmp;
301   }
302
303   T* mPtr;  ///< pointer to RefObject
304 };
305
306 /**
307  * @brief Comparison overrides of objects wrapped by intrusive pointers.
308  *
309  * @SINCE_1_0.0
310  * @param[in] lhs Intrusive pointer to compare with
311  * @param[in] rhs Intrusive pointer to compare against
312  * @return True if the pointers point at the same object
313  */
314 template<typename T, typename U>
315 inline bool operator==( IntrusivePtr<T>const& lhs, IntrusivePtr<U>const& rhs )
316 {
317   return lhs.Get() == rhs.Get();
318 }
319
320 /**
321  * @brief Comparison overrides of objects wrapped by intrusive pointers.
322  *
323  * @SINCE_1_0.0
324  * @param[in] lhs Intrusive pointer to compare with
325  * @param[in] rhs Intrusive pointer to compare against
326  * @return True if the pointers point at different objects
327  */
328 template<typename T, typename U>
329 inline bool operator!=( IntrusivePtr<T>const& lhs, IntrusivePtr<U>const &rhs)
330 {
331   return lhs.Get() != rhs.Get();
332 }
333
334 /**
335  * @brief Comparison overrides of objects wrapped by intrusive pointers.
336  *
337  * @SINCE_1_0.0
338  * @param[in] lhs Intrusive pointer to compare with
339  * @param[in] rhs Object to compare against
340  * @return True if the intrusive pointer points at the specified object
341  */
342 template<typename T, typename U>
343 inline bool operator==( IntrusivePtr<T>const& lhs, U* rhs )
344 {
345   return lhs.Get() == rhs;
346 }
347
348 /**
349  * @brief Comparison overrides of objects wrapped by intrusive pointers.
350  *
351  * @SINCE_1_0.0
352  * @param[in] lhs Intrusive pointer to compare with
353  * @param[in] rhs Intrusive pointer to compare against
354  * @return True if the intrusive pointer doesn't point at the specified object
355  */
356 template<typename T, typename U>
357 inline bool operator!=( IntrusivePtr<T>const& lhs, U* rhs )
358 {
359   return lhs.Get() != rhs;
360 }
361
362 /**
363  * @brief Comparison overrides of objects wrapped by intrusive pointers.
364  *
365  * @SINCE_1_0.0
366  * @param[in] lhs Object to compare with
367  * @param[in] rhs Intrusive pointer to compare against
368  * @return True if the intrusive pointer points at the specified object
369  */
370 template<typename T, typename U>
371 inline bool operator==( T* lhs, IntrusivePtr<U>const& rhs )
372 {
373   return lhs == rhs.Get();
374 }
375
376 /**
377  * @brief Comparison overrides of objects wrapped by intrusive pointers.
378  *
379  * @SINCE_1_0.0
380  * @param[in] lhs Object to compare with
381  * @param[in] rhs Intrusive pointer to compare against
382  * @return True if the intrusive pointer doesn't point at the specified object
383  */
384 template<typename T, typename U>
385 inline bool operator!=( T* lhs, IntrusivePtr<U>const& rhs )
386 {
387   return lhs != rhs.Get();
388 }
389
390 /**
391  * @}
392  */
393 } // namespace Dali
394
395 #endif // DALI_INTRUSIVE_PTR_H