1 #ifndef _DESHAREDPTR_HPP
2 #define _DESHAREDPTR_HPP
3 /*-------------------------------------------------------------------------
4 * drawElements C++ Base Library
5 * -----------------------------
7 * Copyright 2014 The Android Open Source Project
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief Shared pointer.
24 *//*--------------------------------------------------------------------*/
35 //! Shared pointer self-test.
36 void SharedPtr_selfTest (void);
38 class DeadReferenceException : public std::exception
41 DeadReferenceException (void) throw()
46 const char* what (void) const throw()
48 return "DeadReferenceException";
52 struct SharedPtrStateBase
54 SharedPtrStateBase (void)
60 virtual ~SharedPtrStateBase (void) throw() {}
61 virtual void deletePtr (void) throw() = 0;
63 volatile deInt32 strongRefCount;
64 volatile deInt32 weakRefCount; //!< WeakPtr references + StrongPtr references.
67 template<typename Type, typename Deleter>
68 struct SharedPtrState : public SharedPtrStateBase
70 SharedPtrState (Type* ptr, Deleter deleter)
76 virtual ~SharedPtrState (void) throw()
81 virtual void deletePtr (void) throw()
98 /*--------------------------------------------------------------------*//*!
99 * \brief Shared pointer
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.
105 * SharedPtr can also be NULL.
106 *//*--------------------------------------------------------------------*/
112 SharedPtr (const SharedPtr<T>& other);
113 explicit SharedPtr (T* ptr);
115 template<typename Deleter>
116 SharedPtr (T* ptr, Deleter deleter);
119 explicit SharedPtr (const SharedPtr<Y>& other);
122 explicit SharedPtr (const WeakPtr<Y>& other);
127 SharedPtr& operator= (const SharedPtr<Y>& other);
128 SharedPtr& operator= (const SharedPtr<T>& other);
131 SharedPtr& operator= (const WeakPtr<Y>& other);
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.
137 operator bool (void) const throw() { return !!m_ptr; }
139 void swap (SharedPtr<T>& other);
144 operator SharedPtr<Y> (void) const;
148 void acquireFromWeak (const WeakPtr<T>& other);
152 SharedPtrStateBase* m_state;
154 friend class WeakPtr<T>;
157 friend class SharedPtr;
160 /*--------------------------------------------------------------------*//*!
161 * \brief Weak pointer
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
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
171 *//*--------------------------------------------------------------------*/
177 WeakPtr (const WeakPtr<T>& other);
179 explicit WeakPtr (const SharedPtr<T>& other);
182 WeakPtr& operator= (const WeakPtr<T>& other);
183 WeakPtr& operator= (const SharedPtr<T>& other);
185 SharedPtr<T> lock (void);
192 SharedPtrStateBase* m_state;
194 friend class SharedPtr<T>;
197 // SharedPtr template implementation.
199 /*--------------------------------------------------------------------*//*!
200 * \brief Construct empty shared pointer.
201 *//*--------------------------------------------------------------------*/
203 inline SharedPtr<T>::SharedPtr (void)
209 /*--------------------------------------------------------------------*//*!
210 * \brief Construct shared pointer from pointer.
211 * \param ptr Pointer to be managed.
213 * Ownership of the pointer will be transferred to SharedPtr and future
214 * SharedPtr's initialized or assigned from this SharedPtr.
216 * If allocation of shared state fails. The "ptr" argument will not be
218 *//*--------------------------------------------------------------------*/
220 inline SharedPtr<T>::SharedPtr (T* ptr)
227 m_state = new SharedPtrState<T, DefaultDeleter<T> >(ptr, DefaultDeleter<T>());
228 m_state->strongRefCount = 1;
229 m_state->weakRefCount = 1;
233 // \note ptr is not released.
239 /*--------------------------------------------------------------------*//*!
240 * \brief Construct shared pointer from pointer.
241 * \param ptr Pointer to be managed.
243 * Ownership of the pointer will be transferred to SharedPtr and future
244 * SharedPtr's initialized or assigned from this SharedPtr.
246 * Deleter must be callable type and deleter is called with the pointer
247 * argument when the reference count becomes 0.
249 * If allocation of shared state fails. The "ptr" argument will not be
252 * Calling deleter or calling destructor for deleter should never throw.
253 *//*--------------------------------------------------------------------*/
255 template<typename Deleter>
256 inline SharedPtr<T>::SharedPtr (T* ptr, Deleter deleter)
263 m_state = new SharedPtrState<T, Deleter>(ptr, deleter);
264 m_state->strongRefCount = 1;
265 m_state->weakRefCount = 1;
269 // \note ptr is not released.
275 /*--------------------------------------------------------------------*//*!
276 * \brief Initialize shared pointer from another SharedPtr.
277 * \param other Pointer to be shared.
278 *//*--------------------------------------------------------------------*/
280 inline SharedPtr<T>::SharedPtr (const SharedPtr<T>& other)
281 : m_ptr (other.m_ptr)
282 , m_state (other.m_state)
287 /*--------------------------------------------------------------------*//*!
288 * \brief Initialize shared pointer from another SharedPtr.
289 * \param other Pointer to be shared.
291 * Y* must be convertible to T*.
292 *//*--------------------------------------------------------------------*/
295 inline SharedPtr<T>::SharedPtr (const SharedPtr<Y>& other)
296 : m_ptr (other.m_ptr)
297 , m_state (other.m_state)
302 /*--------------------------------------------------------------------*//*!
303 * \brief Initialize shared pointer from weak reference.
304 * \param other Pointer to be shared.
306 * Y* must be convertible to T*.
307 *//*--------------------------------------------------------------------*/
310 inline SharedPtr<T>::SharedPtr (const WeakPtr<Y>& other)
314 acquireFromWeak(other);
318 inline SharedPtr<T>::~SharedPtr (void)
323 /*--------------------------------------------------------------------*//*!
324 * \brief Assign from other shared pointer.
325 * \param other Pointer to be shared.
326 * \return Reference to this SharedPtr.
328 * Reference to current pointer is released and reference to new pointer is
331 * Y* must be convertible to T*.
332 *//*--------------------------------------------------------------------*/
335 inline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<Y>& other)
337 if (m_state == other.m_state)
340 // Release current reference.
343 // Copy from other and acquire reference.
345 m_state = other.m_state;
352 /*--------------------------------------------------------------------*//*!
353 * \brief Assign from other shared pointer.
354 * \param other Pointer to be shared.
355 * \return Reference to this SharedPtr.
357 * Reference to current pointer is released and reference to new pointer is
359 *//*--------------------------------------------------------------------*/
361 inline SharedPtr<T>& SharedPtr<T>::operator= (const SharedPtr<T>& other)
363 if (m_state == other.m_state)
366 // Release current reference.
369 // Copy from other and acquire reference.
371 m_state = other.m_state;
378 /*--------------------------------------------------------------------*//*!
379 * \brief Assign from weak pointer.
380 * \param other Weak reference.
381 * \return Reference to this SharedPtr.
383 * Tries to acquire reference to WeakPtr, releases current reference and
384 * holds reference to new pointer.
386 * If WeakPtr can't be acquired, throws DeadReferenceException and doesn't
387 * release the current reference.
389 * If WeakPtr references same pointer as SharedPtr this call will always
392 * Y* must be convertible to T*.
393 *//*--------------------------------------------------------------------*/
396 inline SharedPtr<T>& SharedPtr<T>::operator= (const WeakPtr<Y>& other)
398 if (m_state == other.m_state)
402 SharedPtr<T> sharedOther(other);
409 /*--------------------------------------------------------------------*//*!
410 * \brief Type conversion operator.
412 * T* must be convertible to Y*.
413 *//*--------------------------------------------------------------------*/
416 inline SharedPtr<T>::operator SharedPtr<Y> (void) const
418 return SharedPtr<Y>(*this);
421 /*--------------------------------------------------------------------*//*!
422 * \brief Compare pointers.
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()
430 return a.get() == b.get();
433 /*--------------------------------------------------------------------*//*!
434 * \brief Compare pointers.
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()
442 return a.get() != b.get();
445 /** Swap pointer contents. */
447 inline void SharedPtr<T>::swap (SharedPtr<T>& other)
450 swap(m_ptr, other.m_ptr);
451 swap(m_state, other.m_state);
454 /** Swap operator for SharedPtr's. */
456 inline void swap (SharedPtr<T>& a, SharedPtr<T>& b)
461 /*--------------------------------------------------------------------*//*!
462 * \brief Set pointer to null.
464 * clear() removes current reference and sets pointer to null value.
465 *//*--------------------------------------------------------------------*/
467 inline void SharedPtr<T>::clear (void)
475 inline void SharedPtr<T>::acquireFromWeak (const WeakPtr<T>& weakRef)
477 DE_ASSERT(!m_ptr && !m_state);
479 SharedPtrStateBase* state = weakRef.m_state;
482 return; // Empty reference.
485 deInt32 oldCount, newCount;
487 // Do atomic compare and increment.
490 oldCount = state->strongRefCount;
492 throw DeadReferenceException();
493 newCount = oldCount+1;
494 } while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount);
496 deAtomicIncrement32(&state->weakRefCount);
499 m_ptr = weakRef.m_ptr;
504 inline void SharedPtr<T>::acquire (void)
508 deAtomicIncrement32(&m_state->strongRefCount);
509 deAtomicIncrement32(&m_state->weakRefCount);
514 inline void SharedPtr<T>::release (void)
518 if (deAtomicDecrement32(&m_state->strongRefCount) == 0)
521 m_state->deletePtr();
524 if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
532 // WeakPtr template implementation.
534 /*--------------------------------------------------------------------*//*!
535 * \brief Construct empty weak pointer.
536 *//*--------------------------------------------------------------------*/
538 inline WeakPtr<T>::WeakPtr (void)
544 /*--------------------------------------------------------------------*//*!
545 * \brief Construct weak pointer from other weak reference.
546 * \param other Weak reference.
547 *//*--------------------------------------------------------------------*/
549 inline WeakPtr<T>::WeakPtr (const WeakPtr<T>& other)
550 : m_ptr (other.m_ptr)
551 , m_state (other.m_state)
556 /*--------------------------------------------------------------------*//*!
557 * \brief Construct weak pointer from shared pointer.
558 * \param other Shared pointer.
559 *//*--------------------------------------------------------------------*/
561 inline WeakPtr<T>::WeakPtr (const SharedPtr<T>& other)
562 : m_ptr (other.m_ptr)
563 , m_state (other.m_state)
569 inline WeakPtr<T>::~WeakPtr (void)
574 /*--------------------------------------------------------------------*//*!
575 * \brief Assign from another weak pointer.
576 * \param other Weak reference.
577 * \return Reference to this WeakPtr.
579 * The current weak reference is removed first and then a new weak reference
580 * to the object pointed by other is taken.
581 *//*--------------------------------------------------------------------*/
583 inline WeakPtr<T>& WeakPtr<T>::operator= (const WeakPtr<T>& other)
591 m_state = other.m_state;
598 /*--------------------------------------------------------------------*//*!
599 * \brief Assign from shared pointer.
600 * \param other Shared pointer.
601 * \return Reference to this WeakPtr.
603 * The current weak reference is removed first and then a new weak reference
604 * to the object pointed by other is taken.
605 *//*--------------------------------------------------------------------*/
607 inline WeakPtr<T>& WeakPtr<T>::operator= (const SharedPtr<T>& other)
612 m_state = other.m_state;
620 inline void WeakPtr<T>::acquire (void)
623 deAtomicIncrement32(&m_state->weakRefCount);
627 inline void WeakPtr<T>::release (void)
631 if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
642 #endif // _DESHAREDPTR_HPP