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 
28 namespace de
29 {
30 
31 //! Unique pointer self-test.
32 void UniquePtr_selfTest (void);
33 
34 // Hide implementation-private types in a details namespace.
35 namespace 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.
41 template<typename T, class D>
42 struct PtrData
43 {
PtrDatade::details::PtrData44 				PtrData	(T* p, D d) : ptr(p), deleter(d) {}
45 
46 				template <typename T2, class D2>
PtrDatade::details::PtrData47 				PtrData	(const PtrData<T2, D2>& d) : ptr(d.ptr), deleter(d.deleter) {}
48 
49 	T*			ptr;
50 	D			deleter;
51 };
52 
53 template<typename T, class D>
54 class UniqueBase
55 {
56 public:
57 	typedef			T				element_type;
58 	typedef			D				deleter_type;
59 
get(void) const60 	T*				get				(void) const throw() { return m_data.ptr;	}	//!< Get stored pointer.
getDeleter(void) const61 	D				getDeleter		(void) const throw() { return m_data.deleter; }
operator ->(void) const62 	T*				operator->		(void) const throw() { return get();	}	//!< Get stored pointer.
operator *(void) const63 	T&				operator*		(void) const throw() { return *get();	}	//!< De-reference stored pointer.
operator bool(void) const64 	operator		bool			(void) const throw() { return !!get();	}
65 
66 protected:
UniqueBase(T * ptr,D deleter)67 					UniqueBase		(T* ptr, D deleter)		: m_data(ptr, deleter) {}
UniqueBase(PtrData<T,D> data)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 
75 private:
76 	PtrData<T, D>	m_data;
77 };
78 
79 template <typename T, class D>
~UniqueBase(void)80 UniqueBase<T, D>::~UniqueBase (void)
81 {
82 	reset();
83 }
84 
85 template <typename T, class D>
reset(void)86 void 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 
95 template <typename T, class D>
releaseData(void)96 PtrData<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 
103 template <typename T, class D>
assignData(PtrData<T,D> data)104 void 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  *//*--------------------------------------------------------------------*/
124 template<typename T, class Deleter = DefaultDeleter<T> >
125 class MovePtr : public UniqueBase<T, Deleter>
126 {
127 public:
MovePtr(void)128 				MovePtr				(void)									: UniqueBase<T, Deleter> (DE_NULL, Deleter()) {}
MovePtr(T * ptr,Deleter deleter=Deleter ())129 	explicit	MovePtr				(T* ptr, Deleter deleter = Deleter())	: UniqueBase<T, Deleter> (ptr, deleter) {}
MovePtr(MovePtr<T,Deleter> & other)130 				MovePtr				(MovePtr<T, Deleter>& other)			: UniqueBase<T, Deleter> (other.releaseData()) {}
131 
132 	MovePtr&	operator=			(MovePtr<T, Deleter>& other);
133 	T*			release				(void) throw();
clear(void)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.
MovePtr(PtrData<T,Deleter> data)140 				MovePtr				(PtrData<T, Deleter> data) : UniqueBase<T, Deleter> (data) {}
141 	MovePtr&	operator=			(PtrData<T, Deleter> data);
142 
143 	template<typename U, class Del2>
operator PtrData<U,Del2>(void)144 	operator	PtrData<U, Del2>	(void) { return this->releaseData(); }
145 };
146 
147 template<typename T, class D>
operator =(PtrData<T,D> data)148 MovePtr<T, D>& MovePtr<T,D>::operator= (PtrData<T, D> data)
149 {
150 	this->assignData(data);
151 	return *this;
152 }
153 
154 template<typename T, class D>
operator =(MovePtr<T,D> & other)155 MovePtr<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.
162 template<typename T, class D>
release(void)163 inline T* MovePtr<T,D>::release (void) throw()
164 {
165 	return this->releaseData().ptr;
166 }
167 
168 //! Construct a MovePtr from a pointer.
169 template<typename T>
movePtr(T * ptr)170 inline MovePtr<T> movePtr (T* ptr)					{ return MovePtr<T>(ptr); }
171 
172 //! Allocate and construct an object and return its address as a MovePtr.
173 template<typename T>
newMovePtr(void)174 inline MovePtr<T> newMovePtr (void)					{ return MovePtr<T>(new T()); }
175 template<typename T, typename P0>
newMovePtr(P0 p0)176 inline MovePtr<T> newMovePtr (P0 p0)				{ return MovePtr<T>(new T(p0)); }
177 template<typename T, typename P0, typename P1>
newMovePtr(P0 p0,P1 p1)178 inline MovePtr<T> newMovePtr (P0 p0, P1 p1)			{ return MovePtr<T>(new T(p0, p1)); }
179 template<typename T, typename P0, typename P1, typename P2>
newMovePtr(P0 p0,P1 p1,P2 p2)180 inline 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  *//*--------------------------------------------------------------------*/
200 template<typename T, class Deleter = DefaultDeleter<T> >
201 class UniquePtr : public UniqueBase<T, Deleter>
202 {
203 public:
204 	explicit				UniquePtr		(T* ptr, Deleter deleter = Deleter());
205 							UniquePtr		(PtrData<T, Deleter> data);
206 	MovePtr<T, Deleter>		move			(void);
207 
208 private:
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  *//*--------------------------------------------------------------------*/
219 template<typename T, class Deleter>
UniquePtr(T * ptr,Deleter deleter)220 inline UniquePtr<T, Deleter>::UniquePtr (T* ptr, Deleter deleter)
221 	: UniqueBase<T, Deleter> (ptr, deleter)
222 {
223 }
224 
225 template<typename T, class Deleter>
UniquePtr(PtrData<T,Deleter> data)226 inline 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  *//*--------------------------------------------------------------------*/
237 template<typename T, class Deleter>
move(void)238 inline MovePtr<T, Deleter> UniquePtr<T, Deleter>::move (void)
239 {
240 	return MovePtr<T, Deleter>(this->releaseData());
241 }
242 
243 } // details
244 
245 using details::UniquePtr;
246 using details::MovePtr;
247 using details::newMovePtr;
248 
249 } // de
250 
251 #endif // _DEUNIQUEPTR_HPP
252