1#ifndef _DEUNIQUEPTR_HPP
2#define _DEUNIQUEPTR_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 Unique pointer.
24 *//*--------------------------------------------------------------------*/
25
26#include "deDefs.hpp"
27
28namespace de
29{
30
31//! Unique pointer self-test.
32void UniquePtr_selfTest (void);
33
34// Hide implementation-private types in a details namespace.
35namespace details
36{
37
38//! Auxiliary struct used to pass references between unique pointers. To
39//! ensure that managed pointers are deleted exactly once, this type should
40//! not appear in user code.
41template<typename T, class D>
42struct PtrData
43{
44				PtrData	(T* p, D d) : ptr(p), deleter(d) {}
45
46				template <typename T2, class D2>
47				PtrData	(const PtrData<T2, D2>& d) : ptr(d.ptr), deleter(d.deleter) {}
48
49	T*			ptr;
50	D			deleter;
51};
52
53template<typename T, class D>
54class UniqueBase
55{
56public:
57	typedef			T				element_type;
58	typedef			D				deleter_type;
59
60	T*				get				(void) const throw() { return m_data.ptr;	}	//!< Get stored pointer.
61	D				getDeleter		(void) const throw() { return m_data.deleter; }
62	T*				operator->		(void) const throw() { return get();	}	//!< Get stored pointer.
63	T&				operator*		(void) const throw() { return *get();	}	//!< De-reference stored pointer.
64	operator		bool			(void) const throw() { return !!get();	}
65
66protected:
67					UniqueBase		(T* ptr, D deleter)		: m_data(ptr, deleter) {}
68					UniqueBase		(PtrData<T, D> data)	: m_data(data) {}
69					~UniqueBase		(void);
70
71	void			reset			(void);					//!< Delete previous pointer, set to null.
72	PtrData<T, D>	releaseData		(void) throw();			//!< Relinquish ownership, return pointer data.
73	void			assignData		(PtrData<T, D> data);	//!< Set new pointer, delete previous pointer.
74
75private:
76	PtrData<T, D>	m_data;
77};
78
79template <typename T, class D>
80UniqueBase<T, D>::~UniqueBase (void)
81{
82	reset();
83}
84
85template <typename T, class D>
86void UniqueBase<T, D>::reset (void)
87{
88	if (m_data.ptr != DE_NULL)
89	{
90		m_data.deleter(m_data.ptr);
91		m_data.ptr = DE_NULL;
92	}
93}
94
95template <typename T, class D>
96PtrData<T, D> UniqueBase<T, D>::releaseData (void) throw()
97{
98	PtrData<T, D> data = m_data;
99	m_data.ptr = DE_NULL;
100	return data;
101}
102
103template <typename T, class D>
104void UniqueBase<T, D>::assignData (PtrData<T, D> data)
105{
106	if (data.ptr != m_data.ptr)
107	{
108		reset();
109		m_data = data;
110	}
111}
112
113/*--------------------------------------------------------------------*//*!
114 * \brief Movable unique pointer
115 *
116 * A MovePtr is smart pointer that retains sole ownership of a pointer and
117 * destroys it when it is destroyed (for example when it goes out of scope).
118 *
119 * A MovePtr can be copied and assigned to. The pointer ownership is moved to
120 * the newly constructer or assigned-to MovePtr. Upon assignment to a
121 * MovePtr, the previously managed pointer is deleted.
122 *
123 *//*--------------------------------------------------------------------*/
124template<typename T, class Deleter = DefaultDeleter<T> >
125class MovePtr : public UniqueBase<T, Deleter>
126{
127public:
128				MovePtr				(void)									: UniqueBase<T, Deleter> (DE_NULL, Deleter()) {}
129	explicit	MovePtr				(T* ptr, Deleter deleter = Deleter())	: UniqueBase<T, Deleter> (ptr, deleter) {}
130				MovePtr				(MovePtr<T, Deleter>& other)			: UniqueBase<T, Deleter> (other.releaseData()) {}
131
132	MovePtr&	operator=			(MovePtr<T, Deleter>& other);
133	T*			release				(void) throw();
134	void		clear				(void) { this->reset(); }
135
136	// These implicit by-value conversions to and from a PtrData are used to
137	// allow copying a MovePtr by value when returning from a function. To
138	// ensure that the managed pointer gets deleted exactly once, the PtrData
139	// should only exist as a temporary conversion step between two MovePtrs.
140				MovePtr				(PtrData<T, Deleter> data) : UniqueBase<T, Deleter> (data) {}
141	MovePtr&	operator=			(PtrData<T, Deleter> data);
142
143	template<typename U, class Del2>
144	operator	PtrData<U, Del2>	(void) { return this->releaseData(); }
145};
146
147template<typename T, class D>
148MovePtr<T, D>& MovePtr<T,D>::operator= (PtrData<T, D> data)
149{
150	this->assignData(data);
151	return *this;
152}
153
154template<typename T, class D>
155MovePtr<T, D>& MovePtr<T,D>::operator= (MovePtr<T, D>& other)
156{
157	return (*this = other.releaseData());
158}
159
160//! Steal the managed pointer. The caller is responsible for explicitly
161//! deleting the returned pointer.
162template<typename T, class D>
163inline T* MovePtr<T,D>::release (void) throw()
164{
165	return this->releaseData().ptr;
166}
167
168//! Construct a MovePtr from a pointer.
169template<typename T>
170inline MovePtr<T> movePtr (T* ptr)					{ return MovePtr<T>(ptr); }
171
172//! Allocate and construct an object and return its address as a MovePtr.
173template<typename T>
174inline MovePtr<T> newMovePtr (void) 				{ return MovePtr<T>(new T()); }
175template<typename T, typename P0>
176inline MovePtr<T> newMovePtr (P0 p0)				{ return MovePtr<T>(new T(p0)); }
177template<typename T, typename P0, typename P1>
178inline MovePtr<T> newMovePtr (P0 p0, P1 p1)			{ return MovePtr<T>(new T(p0, p1)); }
179template<typename T, typename P0, typename P1, typename P2>
180inline MovePtr<T> newMovePtr (P0 p0, P1 p1, P2 p2)	{ return MovePtr<T>(new T(p0, p1, p2)); }
181
182/*--------------------------------------------------------------------*//*!
183 * \brief Unique pointer
184 *
185 * UniquePtr is smart pointer that retains sole ownership of a pointer
186 * and destroys it when UniquePtr is destroyed (for example when UniquePtr
187 * goes out of scope).
188 *
189 * UniquePtr is not copyable or assignable. Pointer ownership can be transferred
190 * from a UniquePtr only explicitly with the move() member function.
191 *
192 * A UniquePtr can be constructed from a MovePtr. In this case it assumes
193 * ownership of the pointer from the MovePtr. Because a UniquePtr cannot be
194 * copied, direct initialization syntax must be used, i.e.:
195 *
196 *		MovePtr<Foo> createFoo (void);
197 * 		UniquePtr<Foo> fooPtr(createFoo()); // NOT fooPtr = createFoo();
198 *
199 *//*--------------------------------------------------------------------*/
200template<typename T, class Deleter = DefaultDeleter<T> >
201class UniquePtr : public UniqueBase<T, Deleter>
202{
203public:
204	explicit				UniquePtr		(T* ptr, Deleter deleter = Deleter());
205							UniquePtr		(PtrData<T, Deleter> data);
206	MovePtr<T, Deleter>		move			(void);
207
208private:
209							UniquePtr		(const UniquePtr<T>& other); // Not allowed!
210	UniquePtr				operator=		(const UniquePtr<T>& other); // Not allowed!
211};
212
213/*--------------------------------------------------------------------*//*!
214 * \brief Construct unique pointer.
215 * \param ptr Pointer to be managed.
216 *
217 * Pointer ownership is transferred to the UniquePtr.
218 *//*--------------------------------------------------------------------*/
219template<typename T, class Deleter>
220inline UniquePtr<T, Deleter>::UniquePtr (T* ptr, Deleter deleter)
221	: UniqueBase<T, Deleter> (ptr, deleter)
222{
223}
224
225template<typename T, class Deleter>
226inline UniquePtr<T, Deleter>::UniquePtr (PtrData<T, Deleter> data)
227	: UniqueBase<T, Deleter> (data)
228{
229}
230
231/*--------------------------------------------------------------------*//*!
232 * \brief Relinquish ownership of pointer.
233 *
234 * This method returns a MovePtr that now owns the pointer. The pointer in
235 * the UniquePtr is set to null.
236 *//*--------------------------------------------------------------------*/
237template<typename T, class Deleter>
238inline MovePtr<T, Deleter> UniquePtr<T, Deleter>::move (void)
239{
240	return MovePtr<T, Deleter>(this->releaseData());
241}
242
243} // details
244
245using details::UniquePtr;
246using details::MovePtr;
247using details::newMovePtr;
248
249} // de
250
251#endif // _DEUNIQUEPTR_HPP
252