Merge "Report tests using Draw*BaseVertex as NotSupported" am: f96636fdfa
[platform/upstream/VK-GL-CTS.git] / framework / delibs / decpp / deSharedPtr.hpp
1 #ifndef _DESHAREDPTR_HPP
2 #define _DESHAREDPTR_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements C++ Base Library
5  * -----------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Shared pointer.
24  *//*--------------------------------------------------------------------*/
25
26 #include "deDefs.hpp"
27 #include "deAtomic.h"
28
29 #include <exception>
30 #include <algorithm>
31
32 namespace de
33 {
34
35 //! Shared pointer self-test.
36 void SharedPtr_selfTest (void);
37
38 class DeadReferenceException : public std::exception
39 {
40 public:
41                                 DeadReferenceException  (void) throw()
42                 : std::exception()
43         {
44         }
45
46         const char*     what                                    (void) const throw()
47         {
48                 return "DeadReferenceException";
49         }
50 };
51
52 struct SharedPtrStateBase
53 {
54         SharedPtrStateBase (void)
55                 : strongRefCount        (0)
56                 , weakRefCount          (0)
57         {
58         }
59
60         virtual                         ~SharedPtrStateBase     (void) throw() {}
61         virtual void            deletePtr                       (void) throw() = 0;
62
63         volatile deInt32        strongRefCount;
64         volatile deInt32        weakRefCount;           //!< WeakPtr references + StrongPtr references.
65 };
66
67 template<typename Type, typename Deleter>
68 struct SharedPtrState : public SharedPtrStateBase
69 {
70         SharedPtrState (Type* ptr, Deleter deleter)
71                 : m_ptr         (ptr)
72                 , m_deleter     (deleter)
73         {
74         }
75
76         virtual ~SharedPtrState (void) throw()
77         {
78                 DE_ASSERT(!m_ptr);
79         }
80
81         virtual void deletePtr (void) throw()
82         {
83                 m_deleter(m_ptr);
84                 m_ptr = DE_NULL;
85         }
86
87 private:
88         Type*           m_ptr;
89         Deleter         m_deleter;
90 };
91
92 template<typename T>
93 class SharedPtr;
94
95 template<typename T>
96 class WeakPtr;
97
98 /*--------------------------------------------------------------------*//*!
99  * \brief Shared pointer
100  *
101  * SharedPtr is smart pointer for managing shared ownership to a pointer.
102  * Multiple SharedPtrs can maintain ownership to the pointer and it is
103  * destructed when last SharedPtr is destroyed.
104  *
105  * SharedPtr can also be NULL.
106  *//*--------------------------------------------------------------------*/
107 template<typename T>
108 class SharedPtr
109 {
110 public:
111                                                                 SharedPtr                       (void);
112                                                                 SharedPtr                       (const SharedPtr<T>& other);
113         explicit                                        SharedPtr                       (T* ptr);
114
115         template<typename Deleter>
116                                                                 SharedPtr                       (T* ptr, Deleter deleter);
117
118         template<typename Y>
119         explicit                                        SharedPtr                       (const SharedPtr<Y>& other);
120
121         template<typename Y>
122         explicit                                        SharedPtr                       (const WeakPtr<Y>& other);
123
124                                                                 ~SharedPtr                      (void);
125
126         template<typename Y>
127         SharedPtr&                                      operator=                       (const SharedPtr<Y>& other);
128         SharedPtr&                                      operator=                       (const SharedPtr<T>& other);
129
130         template<typename Y>
131         SharedPtr&                                      operator=                       (const WeakPtr<Y>& other);
132
133         T*                                                      get                                     (void) const throw() { return m_ptr;    }       //!< Get stored pointer.
134         T*                                                      operator->                      (void) const throw() { return m_ptr;    }       //!< Get stored pointer.
135         T&                                                      operator*                       (void) const throw() { return *m_ptr;   }       //!< De-reference pointer.
136
137         operator                                        bool                            (void) const throw() { return !!m_ptr;  }
138
139         void                                            swap                            (SharedPtr<T>& other);
140
141         void                                            clear                           (void);
142
143         template<typename Y>
144         operator SharedPtr<Y>           (void) const;
145
146 private:
147         void                                            acquire                         (void);
148         void                                            acquireFromWeak         (const WeakPtr<T>& other);
149         void                                            release                         (void);
150
151         T*                                                      m_ptr;
152         SharedPtrStateBase*                     m_state;
153
154         friend class WeakPtr<T>;
155
156         template<typename U>
157         friend class SharedPtr;
158 };
159
160 /*--------------------------------------------------------------------*//*!
161  * \brief Weak pointer
162  *
163  * WeakPtr manages weak references to objects owned by SharedPtr. Shared
164  * pointer can be converted to weak pointer and vice versa. Weak pointer
165  * differs from SharedPtr by not affecting the lifetime of the managed
166  * object.
167  *
168  * WeakPtr can be converted back to SharedPtr but that operation can fail
169  * if the object is no longer live. In such case DeadReferenceException
170  * will be thrown.
171  *//*--------------------------------------------------------------------*/
172 template<typename T>
173 class WeakPtr
174 {
175 public:
176                                                 WeakPtr         (void);
177                                                 WeakPtr         (const WeakPtr<T>& other);
178
179         explicit                        WeakPtr         (const SharedPtr<T>& other);
180                                                 ~WeakPtr        (void);
181
182         WeakPtr&                        operator=       (const WeakPtr<T>& other);
183         WeakPtr&                        operator=       (const SharedPtr<T>& other);
184
185         SharedPtr<T>            lock            (void);
186
187 private:
188         void                            acquire         (void);
189         void                            release         (void);
190
191         T*                                      m_ptr;
192         SharedPtrStateBase*     m_state;
193
194         friend class SharedPtr<T>;
195 };
196
197 // SharedPtr template implementation.
198
199 /*--------------------------------------------------------------------*//*!
200  * \brief Construct empty shared pointer.
201  *//*--------------------------------------------------------------------*/
202 template<typename T>
203 inline SharedPtr<T>::SharedPtr (void)
204         : m_ptr         (DE_NULL)
205         , m_state       (DE_NULL)
206 {
207 }
208
209 /*--------------------------------------------------------------------*//*!
210  * \brief Construct shared pointer from pointer.
211  * \param ptr Pointer to be managed.
212  *
213  * Ownership of the pointer will be transferred to SharedPtr and future
214  * SharedPtr's initialized or assigned from this SharedPtr.
215  *
216  * If allocation of shared state fails. The "ptr" argument will not be
217  * released.
218  *//*--------------------------------------------------------------------*/
219 template<typename T>
220 inline SharedPtr<T>::SharedPtr (T* ptr)
221         : m_ptr         (DE_NULL)
222         , m_state       (DE_NULL)
223 {
224         try
225         {
226                 m_ptr   = ptr;
227                 m_state = new SharedPtrState<T, DefaultDeleter<T> >(ptr, DefaultDeleter<T>());
228                 m_state->strongRefCount = 1;
229                 m_state->weakRefCount   = 1;
230         }
231         catch (...)
232         {
233                 // \note ptr is not released.
234                 delete m_state;
235                 throw;
236         }
237 }
238
239 /*--------------------------------------------------------------------*//*!
240  * \brief Construct shared pointer from pointer.
241  * \param ptr Pointer to be managed.
242  *
243  * Ownership of the pointer will be transferred to SharedPtr and future
244  * SharedPtr's initialized or assigned from this SharedPtr.
245  *
246  * Deleter must be callable type and deleter is called with the pointer
247  * argument when the reference count becomes 0.
248  *
249  * If allocation of shared state fails. The "ptr" argument will not be
250  * released.
251  *
252  * Calling deleter or calling destructor for deleter should never throw.
253  *//*--------------------------------------------------------------------*/
254 template<typename T>
255 template<typename Deleter>
256 inline SharedPtr<T>::SharedPtr (T* ptr, Deleter deleter)
257         : m_ptr         (DE_NULL)
258         , m_state       (DE_NULL)
259 {
260         try
261         {
262                 m_ptr   = ptr;
263                 m_state = new SharedPtrState<T, Deleter>(ptr, deleter);
264                 m_state->strongRefCount = 1;
265                 m_state->weakRefCount   = 1;
266         }
267         catch (...)
268         {
269                 // \note ptr is not released.
270                 delete m_state;
271                 throw;
272         }
273 }
274
275 /*--------------------------------------------------------------------*//*!
276  * \brief Initialize shared pointer from another SharedPtr.
277  * \param other Pointer to be shared.
278  *//*--------------------------------------------------------------------*/
279 template<typename T>
280 inline SharedPtr<T>::SharedPtr (const SharedPtr<T>& other)
281         : m_ptr         (other.m_ptr)
282         , m_state       (other.m_state)
283 {
284         acquire();
285 }
286
287 /*--------------------------------------------------------------------*//*!
288  * \brief Initialize shared pointer from another SharedPtr.
289  * \param other Pointer to be shared.
290  *
291  * Y* must be convertible to T*.
292  *//*--------------------------------------------------------------------*/
293 template<typename T>
294 template<typename Y>
295 inline SharedPtr<T>::SharedPtr (const SharedPtr<Y>& other)
296         : m_ptr         (other.m_ptr)
297         , m_state       (other.m_state)
298 {
299         acquire();
300 }
301
302 /*--------------------------------------------------------------------*//*!
303  * \brief Initialize shared pointer from weak reference.
304  * \param other Pointer to be shared.
305  *
306  * Y* must be convertible to T*.
307  *//*--------------------------------------------------------------------*/
308 template<typename T>
309 template<typename Y>
310 inline SharedPtr<T>::SharedPtr (const WeakPtr<Y>& other)
311         : m_ptr         (DE_NULL)
312         , m_state       (DE_NULL)
313 {
314         acquireFromWeak(other);
315 }
316
317 template<typename T>
318 inline SharedPtr<T>::~SharedPtr (void)
319 {
320         release();
321 }
322
323 /*--------------------------------------------------------------------*//*!
324  * \brief Assign from other shared pointer.
325  * \param other Pointer to be shared.
326  * \return Reference to this SharedPtr.
327  *
328  * Reference to current pointer is released and reference to new pointer is
329  * acquired.
330  *
331  * Y* must be convertible to T*.
332  *//*--------------------------------------------------------------------*/
333 template<typename T>
334 template<typename Y>
335 inline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<Y>& other)
336 {
337         if (m_state == other.m_state)
338                 return *this;
339
340         // Release current reference.
341         release();
342
343         // Copy from other and acquire reference.
344         m_ptr   = other.m_ptr;
345         m_state = other.m_state;
346
347         acquire();
348
349         return *this;
350 }
351
352 /*--------------------------------------------------------------------*//*!
353  * \brief Assign from other shared pointer.
354  * \param other Pointer to be shared.
355  * \return Reference to this SharedPtr.
356  *
357  * Reference to current pointer is released and reference to new pointer is
358  * acquired.
359  *//*--------------------------------------------------------------------*/
360 template<typename T>
361 inline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<T>& other)
362 {
363         if (m_state == other.m_state)
364                 return *this;
365
366         // Release current reference.
367         release();
368
369         // Copy from other and acquire reference.
370         m_ptr   = other.m_ptr;
371         m_state = other.m_state;
372
373         acquire();
374
375         return *this;
376 }
377
378 /*--------------------------------------------------------------------*//*!
379  * \brief Assign from weak pointer.
380  * \param other Weak reference.
381  * \return Reference to this SharedPtr.
382  *
383  * Tries to acquire reference to WeakPtr, releases current reference and
384  * holds reference to new pointer.
385  *
386  * If WeakPtr can't be acquired, throws DeadReferenceException and doesn't
387  * release the current reference.
388  *
389  * If WeakPtr references same pointer as SharedPtr this call will always
390  * succeed.
391  *
392  * Y* must be convertible to T*.
393  *//*--------------------------------------------------------------------*/
394 template<typename T>
395 template<typename Y>
396 inline SharedPtr<T>& SharedPtr<T>::operator= (const WeakPtr<Y>& other)
397 {
398         if (m_state == other.m_state)
399                 return *this;
400
401         {
402                 SharedPtr<T> sharedOther(other);
403                 *this = other;
404         }
405
406         return *this;
407 }
408
409 /*--------------------------------------------------------------------*//*!
410  * \brief Type conversion operator.
411  *
412  * T* must be convertible to Y*.
413  *//*--------------------------------------------------------------------*/
414 template<class T>
415 template<typename Y>
416 inline SharedPtr<T>::operator SharedPtr<Y> (void) const
417 {
418         return SharedPtr<Y>(*this);
419 }
420
421 /*--------------------------------------------------------------------*//*!
422  * \brief Compare pointers.
423  * \param a A
424  * \param b B
425  * \return true if A and B point to same object, false otherwise.
426  *//*--------------------------------------------------------------------*/
427 template<class T, class U>
428 inline bool operator== (const SharedPtr<T>& a, const SharedPtr<U>& b) throw()
429 {
430         return a.get() == b.get();
431 }
432
433 /*--------------------------------------------------------------------*//*!
434  * \brief Compare pointers.
435  * \param a A
436  * \param b B
437  * \return true if A and B point to different objects, false otherwise.
438  *//*--------------------------------------------------------------------*/
439 template<class T, class U>
440 inline bool operator!= (const SharedPtr<T>& a, const SharedPtr<U>& b) throw()
441 {
442         return a.get() != b.get();
443 }
444
445 /** Swap pointer contents. */
446 template<typename T>
447 inline void SharedPtr<T>::swap (SharedPtr<T>& other)
448 {
449         using std::swap;
450         swap(m_ptr,             other.m_ptr);
451         swap(m_state,   other.m_state);
452 }
453
454 /** Swap operator for SharedPtr's. */
455 template<typename T>
456 inline void swap (SharedPtr<T>& a, SharedPtr<T>& b)
457 {
458         a.swap(b);
459 }
460
461 /*--------------------------------------------------------------------*//*!
462  * \brief Set pointer to null.
463  *
464  * clear() removes current reference and sets pointer to null value.
465  *//*--------------------------------------------------------------------*/
466 template<typename T>
467 inline void SharedPtr<T>::clear (void)
468 {
469         release();
470         m_ptr   = DE_NULL;
471         m_state = DE_NULL;
472 }
473
474 template<typename T>
475 inline void SharedPtr<T>::acquireFromWeak (const WeakPtr<T>& weakRef)
476 {
477         DE_ASSERT(!m_ptr && !m_state);
478
479         SharedPtrStateBase* state = weakRef.m_state;
480
481         if (!state)
482                 return; // Empty reference.
483
484         {
485                 deInt32 oldCount, newCount;
486
487                 // Do atomic compare and increment.
488                 do
489                 {
490                         oldCount = state->strongRefCount;
491                         if (oldCount == 0)
492                                 throw DeadReferenceException();
493                         newCount = oldCount+1;
494                 } while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount);
495
496                 deAtomicIncrement32(&state->weakRefCount);
497         }
498
499         m_ptr   = weakRef.m_ptr;
500         m_state = state;
501 }
502
503 template<typename T>
504 inline void SharedPtr<T>::acquire (void)
505 {
506         if (m_state)
507         {
508                 deAtomicIncrement32(&m_state->strongRefCount);
509                 deAtomicIncrement32(&m_state->weakRefCount);
510         }
511 }
512
513 template<typename T>
514 inline void SharedPtr<T>::release (void)
515 {
516         if (m_state)
517         {
518                 if (deAtomicDecrement32(&m_state->strongRefCount) == 0)
519                 {
520                         m_ptr = DE_NULL;
521                         m_state->deletePtr();
522                 }
523
524                 if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
525                 {
526                         delete m_state;
527                         m_state = DE_NULL;
528                 }
529         }
530 }
531
532 // WeakPtr template implementation.
533
534 /*--------------------------------------------------------------------*//*!
535  * \brief Construct empty weak pointer.
536  *//*--------------------------------------------------------------------*/
537 template<typename T>
538 inline WeakPtr<T>::WeakPtr (void)
539         : m_ptr         (DE_NULL)
540         , m_state       (DE_NULL)
541 {
542 }
543
544 /*--------------------------------------------------------------------*//*!
545  * \brief Construct weak pointer from other weak reference.
546  * \param other Weak reference.
547  *//*--------------------------------------------------------------------*/
548 template<typename T>
549 inline WeakPtr<T>::WeakPtr (const WeakPtr<T>& other)
550         : m_ptr         (other.m_ptr)
551         , m_state       (other.m_state)
552 {
553         acquire();
554 }
555
556 /*--------------------------------------------------------------------*//*!
557  * \brief Construct weak pointer from shared pointer.
558  * \param other Shared pointer.
559  *//*--------------------------------------------------------------------*/
560 template<typename T>
561 inline WeakPtr<T>::WeakPtr (const SharedPtr<T>& other)
562         : m_ptr         (other.m_ptr)
563         , m_state       (other.m_state)
564 {
565         acquire();
566 }
567
568 template<typename T>
569 inline WeakPtr<T>::~WeakPtr (void)
570 {
571         release();
572 }
573
574 /*--------------------------------------------------------------------*//*!
575  * \brief Assign from another weak pointer.
576  * \param other Weak reference.
577  * \return Reference to this WeakPtr.
578  *
579  * The current weak reference is removed first and then a new weak reference
580  * to the object pointed by other is taken.
581  *//*--------------------------------------------------------------------*/
582 template<typename T>
583 inline WeakPtr<T>& WeakPtr<T>::operator= (const WeakPtr<T>& other)
584 {
585         if (this == &other)
586                 return *this;
587
588         release();
589
590         m_ptr   = other.m_ptr;
591         m_state = other.m_state;
592
593         acquire();
594
595         return *this;
596 }
597
598 /*--------------------------------------------------------------------*//*!
599  * \brief Assign from shared pointer.
600  * \param other Shared pointer.
601  * \return Reference to this WeakPtr.
602  *
603  * The current weak reference is removed first and then a new weak reference
604  * to the object pointed by other is taken.
605  *//*--------------------------------------------------------------------*/
606 template<typename T>
607 inline WeakPtr<T>& WeakPtr<T>::operator= (const SharedPtr<T>& other)
608 {
609         release();
610
611         m_ptr   = other.m_ptr;
612         m_state = other.m_state;
613
614         acquire();
615
616         return *this;
617 }
618
619 template<typename T>
620 inline void WeakPtr<T>::acquire (void)
621 {
622         if (m_state)
623                 deAtomicIncrement32(&m_state->weakRefCount);
624 }
625
626 template<typename T>
627 inline void WeakPtr<T>::release (void)
628 {
629         if (m_state)
630         {
631                 if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
632                 {
633                         delete m_state;
634                         m_state = DE_NULL;
635                         m_ptr   = DE_NULL;
636                 }
637         }
638 }
639
640 } // de
641
642 #endif // _DESHAREDPTR_HPP