Home | History | Annotate | Download | only in decpp
      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() : std::exception() {}
     42 	const char* what (void) const throw() { return "DeadReferenceException"; }
     43 };
     44 
     45 template<bool threadSafe>
     46 struct ReferenceCount;
     47 
     48 template<> struct ReferenceCount<true>	{ typedef volatile int	Type; };
     49 template<> struct ReferenceCount<false>	{ typedef int			Type; };
     50 
     51 template<class Deleter, bool threadSafe>
     52 struct SharedPtrState
     53 {
     54 	SharedPtrState (Deleter deleter_)
     55 		: strongRefCount	(0)
     56 		, weakRefCount		(0)
     57 		, deleter			(deleter_)
     58 	{
     59 	}
     60 
     61 	typename ReferenceCount<threadSafe>::Type	strongRefCount;
     62 	typename ReferenceCount<threadSafe>::Type	weakRefCount;		//!< WeakPtr references + StrongPtr references.
     63 	Deleter										deleter;
     64 };
     65 
     66 template<typename DstDeleterType, typename SrcDeleterType, bool threadSafe>
     67 SharedPtrState<DstDeleterType, threadSafe>* sharedPtrStateCast (SharedPtrState<SrcDeleterType, threadSafe>* state)
     68 {
     69 	return reinterpret_cast<SharedPtrState<DstDeleterType, threadSafe>*>(state);
     70 }
     71 
     72 template<typename T, class Deleter, bool threadSafe>
     73 class SharedPtr;
     74 
     75 template<typename T, class Deleter, bool threadSafe>
     76 class WeakPtr;
     77 
     78 /*--------------------------------------------------------------------*//*!
     79  * \brief Shared pointer
     80  *
     81  * SharedPtr is smart pointer for managing shared ownership to a pointer.
     82  * Multiple SharedPtr's can maintain ownership to the pointer and it is
     83  * destructed when last SharedPtr is destroyed.
     84  *
     85  * Shared pointers can be assigned (or initialized using copy constructor)
     86  * and in such case the previous reference is first freed and then a new
     87  * reference to the new pointer is acquired.
     88  *
     89  * SharedPtr can also be empty.
     90  *
     91  * If threadSafe template parameter is set to true, it is safe to share
     92  * data using SharedPtr across threads. SharedPtr object itself is not
     93  * thread safe and should not be mutated from multiple threads simultaneously.
     94  *
     95  * \todo [2012-10-26 pyry] Add custom deleter.
     96  *//*--------------------------------------------------------------------*/
     97 template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true>
     98 class SharedPtr
     99 {
    100 public:
    101 								SharedPtr			(void);
    102 								SharedPtr			(const SharedPtr<T, Deleter, threadSafe>& other);
    103 
    104 	template<typename Y>
    105 	explicit					SharedPtr			(Y* ptr, Deleter deleter = Deleter());
    106 
    107 	template<typename Y, class DeleterY>
    108 	explicit					SharedPtr			(const SharedPtr<Y, DeleterY, threadSafe>& other);
    109 
    110 	template<typename Y, class DeleterY>
    111 	explicit					SharedPtr			(const WeakPtr<Y, DeleterY, threadSafe>& other);
    112 
    113 								~SharedPtr			(void);
    114 
    115 	template<typename Y, class DeleterY>
    116 	SharedPtr&					operator=			(const SharedPtr<Y, DeleterY, threadSafe>& other);
    117 	SharedPtr&					operator=			(const SharedPtr<T, Deleter, threadSafe>& other);
    118 
    119 	template<typename Y, class DeleterY>
    120 	SharedPtr&					operator=			(const WeakPtr<Y, DeleterY, threadSafe>& other);
    121 
    122 	T*							get					(void) const throw() { return m_ptr;	}	//!< Get stored pointer.
    123 	T*							operator->			(void) const throw() { return m_ptr;	}	//!< Get stored pointer.
    124 	T&							operator*			(void) const throw() { return *m_ptr;	}	//!< De-reference pointer.
    125 
    126 	operator					bool				(void) const throw() { return !!m_ptr;	}
    127 
    128 	void						swap				(SharedPtr<T, Deleter, threadSafe>& other);
    129 
    130 	void						clear				(void);
    131 
    132 	template<typename Y, class DeleterY>
    133 	operator SharedPtr<Y, DeleterY, threadSafe>	(void) const;
    134 
    135 private:
    136 	void						acquire				(void);
    137 	void						acquireFromWeak		(const WeakPtr<T, Deleter, threadSafe>& other);
    138 	void						release				(void);
    139 
    140 	T*												m_ptr;
    141 	SharedPtrState<Deleter, threadSafe>*			m_state;
    142 
    143 	friend class WeakPtr<T, Deleter, threadSafe>;
    144 
    145 	template<typename U, class DeleterU, bool threadSafeU>
    146 	friend class SharedPtr;
    147 };
    148 
    149 /*--------------------------------------------------------------------*//*!
    150  * \brief Weak pointer
    151  *
    152  * WeakPtr manages weak references to objects owned by SharedPtr. Shared
    153  * pointer can be converted to weak pointer and vice versa. Weak pointer
    154  * differs from SharedPtr by not affecting the lifetime of the managed
    155  * object.
    156  *
    157  * WeakPtr can be converted back to SharedPtr but that operation can fail
    158  * if the object is no longer live. In such case DeadReferenceException
    159  * will be thrown.
    160  *
    161  * \todo [2012-10-26 pyry] Add custom deleter.
    162  *//*--------------------------------------------------------------------*/
    163 template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true>
    164 class WeakPtr
    165 {
    166 public:
    167 						WeakPtr				(void);
    168 						WeakPtr				(const WeakPtr<T, Deleter, threadSafe>& other);
    169 	explicit			WeakPtr				(const SharedPtr<T, Deleter, threadSafe>& other);
    170 						~WeakPtr			(void);
    171 
    172 	WeakPtr&			operator=			(const WeakPtr<T, Deleter, threadSafe>& other);
    173 	WeakPtr&			operator=			(const SharedPtr<T, Deleter, threadSafe>& other);
    174 
    175 	SharedPtr<T, Deleter, threadSafe>	lock	(void);
    176 
    177 private:
    178 	void				acquire				(void);
    179 	void				release				(void);
    180 
    181 	T*										m_ptr;
    182 	SharedPtrState<Deleter, threadSafe>*	m_state;
    183 
    184 	friend class SharedPtr<T, Deleter, threadSafe>;
    185 };
    186 
    187 // SharedPtr template implementation.
    188 
    189 /*--------------------------------------------------------------------*//*!
    190  * \brief Construct empty shared pointer.
    191  *//*--------------------------------------------------------------------*/
    192 template<typename T, class Deleter, bool threadSafe>
    193 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (void)
    194 	: m_ptr		(DE_NULL)
    195 	, m_state	(DE_NULL)
    196 {
    197 }
    198 
    199 /*--------------------------------------------------------------------*//*!
    200  * \brief Construct shared pointer from pointer.
    201  * \param ptr Pointer to be managed.
    202  *
    203  * Ownership of the pointer will be transferred to SharedPtr and future
    204  * SharedPtr's initialized or assigned from this SharedPtr.
    205  *
    206  * Y* must be convertible to T*.
    207  *//*--------------------------------------------------------------------*/
    208 template<typename T, class Deleter, bool threadSafe>
    209 template<typename Y>
    210 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (Y* ptr, Deleter deleter)
    211 	: m_ptr		(DE_NULL)
    212 	, m_state	(DE_NULL)
    213 {
    214 	try
    215 	{
    216 		m_ptr	= ptr;
    217 		m_state	= new SharedPtrState<Deleter, threadSafe>(deleter);
    218 		m_state->strongRefCount	= 1;
    219 		m_state->weakRefCount	= 1;
    220 	}
    221 	catch (...)
    222 	{
    223 		delete m_ptr;
    224 		delete m_state;
    225 		throw;
    226 	}
    227 }
    228 
    229 /*--------------------------------------------------------------------*//*!
    230  * \brief Initialize shared pointer from another SharedPtr.
    231  * \param other Pointer to be shared.
    232  *//*--------------------------------------------------------------------*/
    233 template<typename T, class Deleter, bool threadSafe>
    234 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (const SharedPtr<T, Deleter, threadSafe>& other)
    235 	: m_ptr		(other.m_ptr)
    236 	, m_state	(other.m_state)
    237 {
    238 	acquire();
    239 }
    240 
    241 /*--------------------------------------------------------------------*//*!
    242  * \brief Initialize shared pointer from another SharedPtr.
    243  * \param other Pointer to be shared.
    244  *
    245  * Y* must be convertible to T*.
    246  *//*--------------------------------------------------------------------*/
    247 template<typename T, class Deleter, bool threadSafe>
    248 template<typename Y, class DeleterY>
    249 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (const SharedPtr<Y, DeleterY, threadSafe>& other)
    250 	: m_ptr		(other.m_ptr)
    251 	, m_state	(sharedPtrStateCast<Deleter>(other.m_state))
    252 {
    253 	acquire();
    254 }
    255 
    256 /*--------------------------------------------------------------------*//*!
    257  * \brief Initialize shared pointer from weak reference.
    258  * \param other Pointer to be shared.
    259  *
    260  * Y* must be convertible to T*.
    261  *//*--------------------------------------------------------------------*/
    262 template<typename T, class Deleter, bool threadSafe>
    263 template<typename Y, class DeleterY>
    264 inline SharedPtr<T, Deleter, threadSafe>::SharedPtr (const WeakPtr<Y, DeleterY, threadSafe>& other)
    265 	: m_ptr		(DE_NULL)
    266 	, m_state	(DE_NULL)
    267 {
    268 	acquireFromWeak(other);
    269 }
    270 
    271 template<typename T, class Deleter, bool threadSafe>
    272 inline SharedPtr<T, Deleter, threadSafe>::~SharedPtr (void)
    273 {
    274 	release();
    275 }
    276 
    277 /*--------------------------------------------------------------------*//*!
    278  * \brief Assign from other shared pointer.
    279  * \param other Pointer to be shared.
    280  * \return Reference to this SharedPtr.
    281  *
    282  * Reference to current pointer (if any) will be released first. Then a new
    283  * reference to the pointer managed by other will be acquired.
    284  *
    285  * Y* must be convertible to T*.
    286  *//*--------------------------------------------------------------------*/
    287 template<typename T, class Deleter, bool threadSafe>
    288 template<typename Y, class DeleterY>
    289 inline SharedPtr<T, Deleter, threadSafe>& SharedPtr<T, Deleter, threadSafe>::operator= (const SharedPtr<Y, DeleterY, threadSafe>& other)
    290 {
    291 	if (*this == other)
    292 		return *this;
    293 
    294 	// Release current reference.
    295 	release();
    296 
    297 	// Copy from other and acquire reference.
    298 	m_ptr	= other.m_ptr;
    299 	m_state	= sharedPtrStateCast<Deleter>(other.m_state);
    300 
    301 	acquire();
    302 
    303 	return *this;
    304 }
    305 
    306 /*--------------------------------------------------------------------*//*!
    307  * \brief Assign from other shared pointer.
    308  * \param other Pointer to be shared.
    309  * \return Reference to this SharedPtr.
    310  *
    311  * Reference to current pointer (if any) will be released first. Then a new
    312  * reference to the pointer managed by other will be acquired.
    313  *//*--------------------------------------------------------------------*/
    314 template<typename T, class Deleter, bool threadSafe>
    315 inline SharedPtr<T, Deleter, threadSafe>& SharedPtr<T, Deleter, threadSafe>::operator= (const SharedPtr<T, Deleter, threadSafe>& other)
    316 {
    317 	if (*this == other)
    318 		return *this;
    319 
    320 	// Release current reference.
    321 	release();
    322 
    323 	// Copy from other and acquire reference.
    324 	m_ptr	= other.m_ptr;
    325 	m_state	= other.m_state;
    326 
    327 	acquire();
    328 
    329 	return *this;
    330 }
    331 
    332 /*--------------------------------------------------------------------*//*!
    333  * \brief Assign from weak pointer.
    334  * \param other Weak reference.
    335  * \return Reference to this SharedPtr.
    336  *
    337  * Reference to current pointer (if any) will be released first. Then a
    338  * reference to pointer managed by WeakPtr is acquired if the pointer
    339  * is still live (eg. there's at least one strong reference).
    340  *
    341  * If pointer is no longer live, DeadReferenceException is thrown.
    342  *
    343  * Y* must be convertible to T*.
    344  *//*--------------------------------------------------------------------*/
    345 template<typename T, class Deleter, bool threadSafe>
    346 template<typename Y, class DeleterY>
    347 inline SharedPtr<T, Deleter, threadSafe>& SharedPtr<T, Deleter, threadSafe>::operator= (const WeakPtr<Y, DeleterY, threadSafe>& other)
    348 {
    349 	// Release current reference.
    350 	release();
    351 
    352 	m_ptr	= DE_NULL;
    353 	m_state	= DE_NULL;
    354 
    355 	acquireFromWeak(other);
    356 
    357 	return *this;
    358 }
    359 
    360 /*--------------------------------------------------------------------*//*!
    361  * \brief Type conversion operator.
    362  *
    363  * T* must be convertible to Y*. Since resulting SharedPtr will share the
    364  * ownership destroying Y* must be equal to destroying T*.
    365  *//*--------------------------------------------------------------------*/
    366 template<class T, class Deleter, bool threadSafe>
    367 template<typename Y, class DeleterY>
    368 inline SharedPtr<T, Deleter, threadSafe>::operator SharedPtr<Y, DeleterY, threadSafe> (void) const
    369 {
    370 	return SharedPtr<Y, DeleterY, threadSafe>(*this);
    371 }
    372 
    373 /*--------------------------------------------------------------------*//*!
    374  * \brief Compare pointers.
    375  * \param a A
    376  * \param b B
    377  * \return true if A and B point to same object, false otherwise.
    378  *//*--------------------------------------------------------------------*/
    379 template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU>
    380 inline bool operator== (const SharedPtr<T, DeleterT, threadSafeT>& a, const SharedPtr<U, DeleterU, threadSafeU>& b) throw()
    381 {
    382 	return a.get() == b.get();
    383 }
    384 
    385 /*--------------------------------------------------------------------*//*!
    386  * \brief Compare pointers.
    387  * \param a A
    388  * \param b B
    389  * \return true if A and B point to different objects, false otherwise.
    390  *//*--------------------------------------------------------------------*/
    391 template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU>
    392 inline bool operator!= (const SharedPtr<T, DeleterT, threadSafeT>& a, const SharedPtr<U, DeleterU, threadSafeU>& b) throw()
    393 {
    394 	return a.get() != b.get();
    395 }
    396 
    397 /** Swap pointer contents. */
    398 template<typename T, class Deleter, bool threadSafe>
    399 inline void SharedPtr<T, Deleter, threadSafe>::swap (SharedPtr<T, Deleter, threadSafe>& other)
    400 {
    401 	using std::swap;
    402 	swap(m_ptr,		other.m_ptr);
    403 	swap(m_state,	other.m_state);
    404 }
    405 
    406 /** Swap operator for SharedPtr's. */
    407 template<typename T, class Deleter, bool threadSafe>
    408 inline void swap (SharedPtr<T, Deleter, threadSafe>& a, SharedPtr<T, Deleter, threadSafe>& b)
    409 {
    410 	a.swap(b);
    411 }
    412 
    413 /*--------------------------------------------------------------------*//*!
    414  * \brief Set pointer to null.
    415  *
    416  * clear() removes current reference and sets pointer to null value.
    417  *//*--------------------------------------------------------------------*/
    418 template<typename T, class Deleter, bool threadSafe>
    419 inline void SharedPtr<T, Deleter, threadSafe>::clear (void)
    420 {
    421 	release();
    422 	m_ptr	= DE_NULL;
    423 	m_state	= DE_NULL;
    424 }
    425 
    426 template<typename T, class Deleter, bool threadSafe>
    427 inline void SharedPtr<T, Deleter, threadSafe>::acquireFromWeak (const WeakPtr<T, Deleter, threadSafe>& weakRef)
    428 {
    429 	DE_ASSERT(!m_ptr && !m_state);
    430 
    431 	SharedPtrState<Deleter, threadSafe>* state = weakRef.m_state;
    432 
    433 	if (!state)
    434 		return; // Empty reference.
    435 
    436 	if (threadSafe)
    437 	{
    438 		int oldCount, newCount;
    439 
    440 		// Do atomic compare and increment.
    441 		do
    442 		{
    443 			oldCount = state->strongRefCount;
    444 			if (oldCount == 0)
    445 				throw DeadReferenceException();
    446 			newCount = oldCount+1;
    447 		} while (deAtomicCompareExchange32((deUint32 volatile*)&state->strongRefCount, (deUint32)oldCount, (deUint32)newCount) != (deUint32)oldCount);
    448 
    449 		deAtomicIncrement32(&state->weakRefCount);
    450 	}
    451 	else
    452 	{
    453 		if (state->strongRefCount == 0)
    454 			throw DeadReferenceException();
    455 
    456 		state->strongRefCount	+= 1;
    457 		state->weakRefCount		+= 1;
    458 	}
    459 
    460 	m_ptr	= weakRef.m_ptr;
    461 	m_state	= state;
    462 }
    463 
    464 template<typename T, class Deleter, bool threadSafe>
    465 inline void SharedPtr<T, Deleter, threadSafe>::acquire (void)
    466 {
    467 	if (m_state)
    468 	{
    469 		if (threadSafe)
    470 		{
    471 			deAtomicIncrement32((deInt32 volatile*)&m_state->strongRefCount);
    472 			deAtomicIncrement32((deInt32 volatile*)&m_state->weakRefCount);
    473 		}
    474 		else
    475 		{
    476 			m_state->strongRefCount	+= 1;
    477 			m_state->weakRefCount	+= 1;
    478 		}
    479 	}
    480 }
    481 
    482 template<typename T, class Deleter, bool threadSafe>
    483 inline void SharedPtr<T, Deleter, threadSafe>::release (void)
    484 {
    485 	if (m_state)
    486 	{
    487 		if (threadSafe)
    488 		{
    489 			if (deAtomicDecrement32(&m_state->strongRefCount) == 0)
    490 			{
    491 				m_state->deleter(m_ptr);
    492 				m_ptr = DE_NULL;
    493 			}
    494 
    495 			if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
    496 			{
    497 				delete m_state;
    498 				m_state = DE_NULL;
    499 			}
    500 		}
    501 		else
    502 		{
    503 			m_state->strongRefCount	-= 1;
    504 			m_state->weakRefCount	-= 1;
    505 			DE_ASSERT(m_state->strongRefCount >= 0 && m_state->weakRefCount >= 0);
    506 
    507 			if (m_state->strongRefCount == 0)
    508 			{
    509 				m_state->deleter(m_ptr);
    510 				m_ptr = DE_NULL;
    511 			}
    512 
    513 			if (m_state->weakRefCount == 0)
    514 			{
    515 				delete m_state;
    516 				m_state = DE_NULL;
    517 			}
    518 		}
    519 	}
    520 }
    521 
    522 // WeakPtr template implementation.
    523 
    524 /*--------------------------------------------------------------------*//*!
    525  * \brief Construct empty weak pointer.
    526  *//*--------------------------------------------------------------------*/
    527 template<typename T, class Deleter, bool threadSafe>
    528 inline WeakPtr<T, Deleter, threadSafe>::WeakPtr (void)
    529 	: m_ptr		(DE_NULL)
    530 	, m_state	(DE_NULL)
    531 {
    532 }
    533 
    534 /*--------------------------------------------------------------------*//*!
    535  * \brief Construct weak pointer from other weak reference.
    536  * \param other Weak reference.
    537  *//*--------------------------------------------------------------------*/
    538 template<typename T, class Deleter, bool threadSafe>
    539 inline WeakPtr<T, Deleter, threadSafe>::WeakPtr (const WeakPtr<T, Deleter, threadSafe>& other)
    540 	: m_ptr		(other.m_ptr)
    541 	, m_state	(other.m_state)
    542 {
    543 	acquire();
    544 }
    545 
    546 /*--------------------------------------------------------------------*//*!
    547  * \brief Construct weak pointer from shared pointer.
    548  * \param other Shared pointer.
    549  *//*--------------------------------------------------------------------*/
    550 template<typename T, class Deleter, bool threadSafe>
    551 inline WeakPtr<T, Deleter, threadSafe>::WeakPtr (const SharedPtr<T, Deleter, threadSafe>& other)
    552 	: m_ptr		(other.m_ptr)
    553 	, m_state	(other.m_state)
    554 {
    555 	acquire();
    556 }
    557 
    558 template<typename T, class Deleter, bool threadSafe>
    559 inline WeakPtr<T, Deleter, threadSafe>::~WeakPtr (void)
    560 {
    561 	release();
    562 }
    563 
    564 /*--------------------------------------------------------------------*//*!
    565  * \brief Assign from another weak pointer.
    566  * \param other Weak reference.
    567  * \return Reference to this WeakPtr.
    568  *
    569  * The current weak reference is removed first and then a new weak reference
    570  * to the object pointed by other is taken.
    571  *//*--------------------------------------------------------------------*/
    572 template<typename T, class Deleter, bool threadSafe>
    573 inline WeakPtr<T, Deleter, threadSafe>& WeakPtr<T, Deleter, threadSafe>::operator= (const WeakPtr<T, Deleter, threadSafe>& other)
    574 {
    575 	if (this == &other)
    576 		return *this;
    577 
    578 	release();
    579 
    580 	m_ptr	= other.m_ptr;
    581 	m_state	= other.m_state;
    582 
    583 	acquire();
    584 
    585 	return *this;
    586 }
    587 
    588 /*--------------------------------------------------------------------*//*!
    589  * \brief Assign from shared pointer.
    590  * \param other Shared pointer.
    591  * \return Reference to this WeakPtr.
    592  *
    593  * The current weak reference is removed first and then a new weak reference
    594  * to the object pointed by other is taken.
    595  *//*--------------------------------------------------------------------*/
    596 template<typename T, class Deleter, bool threadSafe>
    597 inline WeakPtr<T, Deleter, threadSafe>& WeakPtr<T, Deleter, threadSafe>::operator= (const SharedPtr<T, Deleter, threadSafe>& other)
    598 {
    599 	release();
    600 
    601 	m_ptr	= other.m_ptr;
    602 	m_state	= other.m_state;
    603 
    604 	acquire();
    605 
    606 	return *this;
    607 }
    608 
    609 template<typename T, class Deleter, bool threadSafe>
    610 inline void WeakPtr<T, Deleter, threadSafe>::acquire (void)
    611 {
    612 	if (m_state)
    613 	{
    614 		if (threadSafe)
    615 			deAtomicIncrement32(&m_state->weakRefCount);
    616 		else
    617 			m_state->weakRefCount += 1;
    618 	}
    619 }
    620 
    621 template<typename T, class Deleter, bool threadSafe>
    622 inline void WeakPtr<T, Deleter, threadSafe>::release (void)
    623 {
    624 	if (m_state)
    625 	{
    626 		if (threadSafe)
    627 		{
    628 			if (deAtomicDecrement32(&m_state->weakRefCount) == 0)
    629 			{
    630 				delete m_state;
    631 				m_state	= DE_NULL;
    632 				m_ptr	= DE_NULL;
    633 			}
    634 		}
    635 		else
    636 		{
    637 			m_state->weakRefCount -= 1;
    638 			DE_ASSERT(m_state->weakRefCount >= 0);
    639 
    640 			if (m_state->weakRefCount == 0)
    641 			{
    642 				delete m_state;
    643 				m_state	= DE_NULL;
    644 				m_ptr	= DE_NULL;
    645 			}
    646 		}
    647 	}
    648 }
    649 
    650 } // de
    651 
    652 #endif // _DESHAREDPTR_HPP
    653