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