xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deUniquePtr.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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     }
47 
48     template <typename T2, class D2>
PtrDatade::details::PtrData49     PtrData(const PtrData<T2, D2> &d) : ptr(d.ptr)
50                                       , deleter(d.deleter)
51     {
52     }
53 
54     T *ptr;
55     D deleter;
56 };
57 
58 template <typename T, class D>
59 class UniqueBase
60 {
61 public:
62     typedef T element_type;
63     typedef D deleter_type;
64 
get(void) const65     T *get(void) const throw()
66     {
67         return m_data.ptr;
68     } //!< Get stored pointer.
getDeleter(void) const69     D getDeleter(void) const throw()
70     {
71         return m_data.deleter;
72     }
operator ->(void) const73     T *operator->(void) const throw()
74     {
75         return get();
76     } //!< Get stored pointer.
operator *(void) const77     T &operator*(void) const throw()
78     {
79         return *get();
80     } //!< De-reference stored pointer.
operator bool(void) const81     operator bool(void) const throw()
82     {
83         return !!get();
84     }
85 
86 protected:
UniqueBase(T * ptr,D deleter)87     UniqueBase(T *ptr, D deleter) : m_data(ptr, deleter)
88     {
89     }
UniqueBase(PtrData<T,D> data)90     UniqueBase(PtrData<T, D> data) : m_data(data)
91     {
92     }
93     ~UniqueBase(void);
94 
95     void reset(void);                        //!< Delete previous pointer, set to null.
96     PtrData<T, D> releaseData(void) throw(); //!< Relinquish ownership, return pointer data.
97     void assignData(PtrData<T, D> data);     //!< Set new pointer, delete previous pointer.
98 
99 private:
100     PtrData<T, D> m_data;
101 };
102 
103 template <typename T, class D>
~UniqueBase(void)104 UniqueBase<T, D>::~UniqueBase(void)
105 {
106     reset();
107 }
108 
109 template <typename T, class D>
reset(void)110 void UniqueBase<T, D>::reset(void)
111 {
112     if (m_data.ptr != DE_NULL)
113     {
114         m_data.deleter(m_data.ptr);
115         m_data.ptr = DE_NULL;
116     }
117 }
118 
119 template <typename T, class D>
releaseData(void)120 PtrData<T, D> UniqueBase<T, D>::releaseData(void) throw()
121 {
122     PtrData<T, D> data = m_data;
123     m_data.ptr         = DE_NULL;
124     return data;
125 }
126 
127 template <typename T, class D>
assignData(PtrData<T,D> data)128 void UniqueBase<T, D>::assignData(PtrData<T, D> data)
129 {
130     if (data.ptr != m_data.ptr)
131     {
132         reset();
133         m_data = data;
134     }
135 }
136 
137 /*--------------------------------------------------------------------*//*!
138  * \brief Movable unique pointer
139  *
140  * A MovePtr is smart pointer that retains sole ownership of a pointer and
141  * destroys it when it is destroyed (for example when it goes out of scope).
142  *
143  * A MovePtr can be copied and assigned to. The pointer ownership is moved to
144  * the newly constructer or assigned-to MovePtr. Upon assignment to a
145  * MovePtr, the previously managed pointer is deleted.
146  *
147  *//*--------------------------------------------------------------------*/
148 template <typename T, class Deleter = DefaultDeleter<T>>
149 class MovePtr : public UniqueBase<T, Deleter>
150 {
151 public:
MovePtr(void)152     MovePtr(void) : UniqueBase<T, Deleter>(DE_NULL, Deleter())
153     {
154     }
MovePtr(T * ptr,Deleter deleter=Deleter ())155     explicit MovePtr(T *ptr, Deleter deleter = Deleter()) : UniqueBase<T, Deleter>(ptr, deleter)
156     {
157     }
MovePtr(MovePtr<T,Deleter> & other)158     MovePtr(MovePtr<T, Deleter> &other) : UniqueBase<T, Deleter>(other.releaseData())
159     {
160     }
161 
162     MovePtr &operator=(MovePtr<T, Deleter> &other);
163     T *release(void) throw();
clear(void)164     void clear(void)
165     {
166         this->reset();
167     }
168 
169     // These implicit by-value conversions to and from a PtrData are used to
170     // allow copying a MovePtr by value when returning from a function. To
171     // ensure that the managed pointer gets deleted exactly once, the PtrData
172     // should only exist as a temporary conversion step between two MovePtrs.
MovePtr(PtrData<T,Deleter> data)173     MovePtr(PtrData<T, Deleter> data) : UniqueBase<T, Deleter>(data)
174     {
175     }
176     MovePtr &operator=(PtrData<T, Deleter> data);
177 
178     template <typename U, class Del2>
operator PtrData<U,Del2>(void)179     operator PtrData<U, Del2>(void)
180     {
181         return this->releaseData();
182     }
183 };
184 
185 template <typename T, class D>
operator =(PtrData<T,D> data)186 MovePtr<T, D> &MovePtr<T, D>::operator=(PtrData<T, D> data)
187 {
188     this->assignData(data);
189     return *this;
190 }
191 
192 template <typename T, class D>
operator =(MovePtr<T,D> & other)193 MovePtr<T, D> &MovePtr<T, D>::operator=(MovePtr<T, D> &other)
194 {
195     return (*this = other.releaseData());
196 }
197 
198 //! Steal the managed pointer. The caller is responsible for explicitly
199 //! deleting the returned pointer.
200 template <typename T, class D>
release(void)201 inline T *MovePtr<T, D>::release(void) throw()
202 {
203     return this->releaseData().ptr;
204 }
205 
206 //! Construct a MovePtr from a pointer.
207 template <typename T>
movePtr(T * ptr)208 inline MovePtr<T> movePtr(T *ptr)
209 {
210     return MovePtr<T>(ptr);
211 }
212 
213 //! Allocate and construct an object and return its address as a MovePtr.
214 template <typename T>
newMovePtr(void)215 inline MovePtr<T> newMovePtr(void)
216 {
217     return MovePtr<T>(new T());
218 }
219 template <typename T, typename P0>
newMovePtr(P0 p0)220 inline MovePtr<T> newMovePtr(P0 p0)
221 {
222     return MovePtr<T>(new T(p0));
223 }
224 template <typename T, typename P0, typename P1>
newMovePtr(P0 p0,P1 p1)225 inline MovePtr<T> newMovePtr(P0 p0, P1 p1)
226 {
227     return MovePtr<T>(new T(p0, p1));
228 }
229 template <typename T, typename P0, typename P1, typename P2>
newMovePtr(P0 p0,P1 p1,P2 p2)230 inline MovePtr<T> newMovePtr(P0 p0, P1 p1, P2 p2)
231 {
232     return MovePtr<T>(new T(p0, p1, p2));
233 }
234 
235 /*--------------------------------------------------------------------*//*!
236  * \brief Unique pointer
237  *
238  * UniquePtr is smart pointer that retains sole ownership of a pointer
239  * and destroys it when UniquePtr is destroyed (for example when UniquePtr
240  * goes out of scope).
241  *
242  * UniquePtr is not copyable or assignable. Pointer ownership can be transferred
243  * from a UniquePtr only explicitly with the move() member function.
244  *
245  * A UniquePtr can be constructed from a MovePtr. In this case it assumes
246  * ownership of the pointer from the MovePtr. Because a UniquePtr cannot be
247  * copied, direct initialization syntax must be used, i.e.:
248  *
249  *        MovePtr<Foo> createFoo (void);
250  *        UniquePtr<Foo> fooPtr(createFoo()); // NOT fooPtr = createFoo();
251  *
252  *//*--------------------------------------------------------------------*/
253 template <typename T, class Deleter = DefaultDeleter<T>>
254 class UniquePtr : public UniqueBase<T, Deleter>
255 {
256 public:
257     explicit UniquePtr(T *ptr, Deleter deleter = Deleter());
258     UniquePtr(PtrData<T, Deleter> data);
259     MovePtr<T, Deleter> move(void);
260 
261 private:
262     UniquePtr(const UniquePtr<T> &other);           // Not allowed!
263     UniquePtr operator=(const UniquePtr<T> &other); // Not allowed!
264 };
265 
266 /*--------------------------------------------------------------------*//*!
267  * \brief Construct unique pointer.
268  * \param ptr Pointer to be managed.
269  *
270  * Pointer ownership is transferred to the UniquePtr.
271  *//*--------------------------------------------------------------------*/
272 template <typename T, class Deleter>
UniquePtr(T * ptr,Deleter deleter)273 inline UniquePtr<T, Deleter>::UniquePtr(T *ptr, Deleter deleter) : UniqueBase<T, Deleter>(ptr, deleter)
274 {
275 }
276 
277 template <typename T, class Deleter>
UniquePtr(PtrData<T,Deleter> data)278 inline UniquePtr<T, Deleter>::UniquePtr(PtrData<T, Deleter> data) : UniqueBase<T, Deleter>(data)
279 {
280 }
281 
282 /*--------------------------------------------------------------------*//*!
283  * \brief Relinquish ownership of pointer.
284  *
285  * This method returns a MovePtr that now owns the pointer. The pointer in
286  * the UniquePtr is set to null.
287  *//*--------------------------------------------------------------------*/
288 template <typename T, class Deleter>
move(void)289 inline MovePtr<T, Deleter> UniquePtr<T, Deleter>::move(void)
290 {
291     return MovePtr<T, Deleter>(this->releaseData());
292 }
293 
294 } // namespace details
295 
296 using details::MovePtr;
297 using details::newMovePtr;
298 using details::UniquePtr;
299 
300 } // namespace de
301 
302 #endif // _DEUNIQUEPTR_HPP
303