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