Home | History | Annotate | Download | only in decpp
      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 {
     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 
     53 template<typename T, class D>
     54 class UniqueBase
     55 {
     56 public:
     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 
     66 protected:
     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 
     75 private:
     76 	PtrData<T, D>	m_data;
     77 };
     78 
     79 template <typename T, class D>
     80 UniqueBase<T, D>::~UniqueBase (void)
     81 {
     82 	reset();
     83 }
     84 
     85 template <typename T, class D>
     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>
     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>
    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:
    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 
    147 template<typename T, class D>
    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>
    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>
    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>
    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>
    174 inline MovePtr<T> newMovePtr (void) 				{ return MovePtr<T>(new T()); }
    175 template<typename T, typename P0>
    176 inline MovePtr<T> newMovePtr (P0 p0)				{ return MovePtr<T>(new T(p0)); }
    177 template<typename T, typename P0, typename 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>
    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>
    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>
    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>
    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