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
32namespace de
33{
34
35//! Shared pointer self-test.
36void SharedPtr_selfTest (void);
37
38class DeadReferenceException : public std::exception
39{
40public:
41	DeadReferenceException (void) throw() : std::exception() {}
42	const char* what (void) const throw() { return "DeadReferenceException"; }
43};
44
45template<bool threadSafe>
46struct ReferenceCount;
47
48template<> struct ReferenceCount<true>	{ typedef volatile int	Type; };
49template<> struct ReferenceCount<false>	{ typedef int			Type; };
50
51template<class Deleter, bool threadSafe>
52struct 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
66template<typename DstDeleterType, typename SrcDeleterType, bool threadSafe>
67SharedPtrState<DstDeleterType, threadSafe>* sharedPtrStateCast (SharedPtrState<SrcDeleterType, threadSafe>* state)
68{
69	return reinterpret_cast<SharedPtrState<DstDeleterType, threadSafe>*>(state);
70}
71
72template<typename T, class Deleter, bool threadSafe>
73class SharedPtr;
74
75template<typename T, class Deleter, bool threadSafe>
76class 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 *//*--------------------------------------------------------------------*/
97template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true>
98class SharedPtr
99{
100public:
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
135private:
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 *//*--------------------------------------------------------------------*/
163template<typename T, class Deleter = DefaultDeleter<T>, bool threadSafe = true>
164class WeakPtr
165{
166public:
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
177private:
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 *//*--------------------------------------------------------------------*/
192template<typename T, class Deleter, bool threadSafe>
193inline 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 *//*--------------------------------------------------------------------*/
208template<typename T, class Deleter, bool threadSafe>
209template<typename Y>
210inline 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 *//*--------------------------------------------------------------------*/
233template<typename T, class Deleter, bool threadSafe>
234inline 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 *//*--------------------------------------------------------------------*/
247template<typename T, class Deleter, bool threadSafe>
248template<typename Y, class DeleterY>
249inline 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 *//*--------------------------------------------------------------------*/
262template<typename T, class Deleter, bool threadSafe>
263template<typename Y, class DeleterY>
264inline 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
271template<typename T, class Deleter, bool threadSafe>
272inline 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 *//*--------------------------------------------------------------------*/
287template<typename T, class Deleter, bool threadSafe>
288template<typename Y, class DeleterY>
289inline 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 *//*--------------------------------------------------------------------*/
314template<typename T, class Deleter, bool threadSafe>
315inline 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 *//*--------------------------------------------------------------------*/
345template<typename T, class Deleter, bool threadSafe>
346template<typename Y, class DeleterY>
347inline 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 *//*--------------------------------------------------------------------*/
366template<class T, class Deleter, bool threadSafe>
367template<typename Y, class DeleterY>
368inline 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 *//*--------------------------------------------------------------------*/
379template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU>
380inline 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 *//*--------------------------------------------------------------------*/
391template<class T, class DeleterT, bool threadSafeT, class U, class DeleterU, bool threadSafeU>
392inline 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. */
398template<typename T, class Deleter, bool threadSafe>
399inline 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. */
407template<typename T, class Deleter, bool threadSafe>
408inline 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 *//*--------------------------------------------------------------------*/
418template<typename T, class Deleter, bool threadSafe>
419inline void SharedPtr<T, Deleter, threadSafe>::clear (void)
420{
421	release();
422	m_ptr	= DE_NULL;
423	m_state	= DE_NULL;
424}
425
426template<typename T, class Deleter, bool threadSafe>
427inline 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
464template<typename T, class Deleter, bool threadSafe>
465inline 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
482template<typename T, class Deleter, bool threadSafe>
483inline 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 *//*--------------------------------------------------------------------*/
527template<typename T, class Deleter, bool threadSafe>
528inline 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 *//*--------------------------------------------------------------------*/
538template<typename T, class Deleter, bool threadSafe>
539inline 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 *//*--------------------------------------------------------------------*/
550template<typename T, class Deleter, bool threadSafe>
551inline 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
558template<typename T, class Deleter, bool threadSafe>
559inline 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 *//*--------------------------------------------------------------------*/
572template<typename T, class Deleter, bool threadSafe>
573inline 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 *//*--------------------------------------------------------------------*/
596template<typename T, class Deleter, bool threadSafe>
597inline 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
609template<typename T, class Deleter, bool threadSafe>
610inline 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
621template<typename T, class Deleter, bool threadSafe>
622inline 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