Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(408)

Side by Side Diff: include/private/SkUniquePtr.h

Issue 1330503006: Add skstd::unique_ptr and use it. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Formatting. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/private/SkTemplates.h ('k') | include/private/SkUtility.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef SkUniquePtr_DEFINED
9 #define SkUniquePtr_DEFINED
10
11 #include "SkTLogic.h"
12 #include "SkUtility.h"
13
14 namespace skstd {
15
16 template <typename T> struct default_delete {
17 /*constexpr*/ default_delete() /*noexcept*/ = default;
18
19 template <typename U, typename = enable_if_t<is_convertible<U*, T*>::value>>
20 default_delete(const default_delete<U>&) /*noexcept*/ {}
21
22 void operator()(T* obj) const {
23 static_assert(sizeof(T) > 0, "Deleting pointer to incomplete type!");
24 delete obj;
25 }
26 };
27 template <typename T> struct default_delete<T[]> {
28 /*constexpr*/ default_delete() /*noexcept*/ = default;
29
30 void operator()(T* obj) const {
31 static_assert(sizeof(T) > 0, "Deleting pointer to incomplete type!");
32 delete [] obj;
33 }
34 };
35
36 template <typename T, typename D = default_delete<T>> class unique_ptr {
37 // remove_reference_t<D>::pointer if that type exists, otherwise T*.
38 struct pointer_type_detector {
39 template <typename U> static typename U::pointer detector(typename U::po inter*);
40 template <typename U> static T* detector(...);
41 using type = decltype(detector<remove_reference_t<D>>(0));
42 };
43
44 public:
45 using pointer = typename pointer_type_detector::type;
46 using element_type = T;
47 using deleter_type = D;
48
49 private:
50 template <typename B, bool = is_empty<B>::value /*&& !is_final<B>::value*/>
51 struct compressed_base : private B {
52 /*constexpr*/ compressed_base() : B() {}
53 /*constexpr*/ compressed_base(const B& b) : B(b) {}
54 /*constexpr*/ compressed_base(const B&& b) : B(move(b)) {}
55 /*constexpr*/ B& get() /*noexcept*/ { return *this; }
56 /*constexpr*/ B const& get() const /*noexcept*/ { return *this; }
57 void swap(compressed_base&) /*noexcept*/ { }
58 };
59
60 template <typename B> struct compressed_base<B, false> {
61 B fb;
62 /*constexpr*/ compressed_base() : B() {}
63 /*constexpr*/ compressed_base(const B& b) : fb(b) {}
64 /*constexpr*/ compressed_base(const B&& b) : fb(move(b)) {}
65 /*constexpr*/ B& get() /*noexcept*/ { return fb; }
66 /*constexpr*/ B const& get() const /*noexcept*/ { return fb; }
67 void swap(compressed_base& that) /*noexcept*/ { SkTSwap(fb, that.fB); }
68 };
69
70 struct compressed_data : private compressed_base<deleter_type> {
71 pointer fPtr;
72 /*constexpr*/ compressed_data() : compressed_base<deleter_type>(), fPtr( ) {}
73 /*constexpr*/ compressed_data(const pointer& ptr, const deleter_type& d)
74 : compressed_base<deleter_type>(d), fPtr(ptr) {}
75 template <typename U1, typename U2, typename = enable_if_t<
76 is_convertible<U1, pointer>::value && is_convertible<U2, deleter_typ e>::value
77 >> /*constexpr*/ compressed_data(U1&& ptr, U2&& d)
78 : compressed_base<deleter_type>(skstd::forward<U2>(d)), fPtr(skstd:: forward<U1>(ptr)) {}
79 /*constexpr*/ pointer& getPointer() /*noexcept*/ { return fPtr; }
80 /*constexpr*/ pointer const& getPointer() const /*noexcept*/ { return fP tr; }
81 /*constexpr*/ deleter_type& getDeleter() /*noexcept*/ {
82 return compressed_base<deleter_type>::get();
83 }
84 /*constexpr*/ deleter_type const& getDeleter() const /*noexcept*/ {
85 return compressed_base<deleter_type>::get();
86 }
87 void swap(compressed_data& that) /*noexcept*/ {
88 compressed_base<deleter_type>::swap(static_cast<compressed_base<dele ter_type>>(that));
89 SkTSwap(fPtr, that.fPtr);
90 }
91 };
92 compressed_data data;
93
94 public:
95 /*constexpr*/ unique_ptr() /*noexcept*/ : data() {
96 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
97 }
98
99 /*constexpr*/ unique_ptr(skstd::nullptr_t) /*noexcept*/ : unique_ptr() { }
100
101 explicit unique_ptr(pointer ptr) /*noexcept*/ : data(ptr, deleter_type()) {
102 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
103 }
104
105 unique_ptr(pointer ptr,
106 conditional_t<is_reference<deleter_type>::value, deleter_type,con st deleter_type&> d)
107 /*noexcept*/ : data(ptr, d)
108 {}
109
110 unique_ptr(pointer ptr, remove_reference_t<deleter_type>&& d) /*noexcept*/
111 : data(move(ptr), move(d))
112 {
113 static_assert(!is_reference<deleter_type>::value,
114 "Binding an rvalue reference deleter as an lvalue reference deleter is not allowed.");
115 }
116
117
118 unique_ptr(unique_ptr&& that) /*noexcept*/
119 : data(that.release(), forward<deleter_type>(that.get_deleter()))
120 {}
121
122 template <typename U, typename ThatD, typename = enable_if_t<
123 is_convertible<typename unique_ptr<U, ThatD>::pointer, pointer>::value & &
124 !is_array<U>::value &&
125 conditional_t<is_reference<D>::value, is_same<ThatD, D>, is_convertible< ThatD, D>>::value>>
126 unique_ptr(unique_ptr<U, ThatD>&& that) /*noexcept*/
127 : data(that.release(), forward<ThatD>(that.get_deleter()))
128 {}
129
130 ~unique_ptr() /*noexcept*/ {
131 pointer& ptr = data.getPointer();
132 if (ptr != nullptr) {
133 get_deleter()(ptr);
134 }
135 ptr = pointer();
136 }
137
138 unique_ptr& operator=(unique_ptr&& that) /*noexcept*/ {
139 reset(that.release());
140 get_deleter() = forward<deleter_type>(that.get_deleter());
141 return *this;
142 }
143
144 template <typename U, typename ThatD> enable_if_t<
145 is_convertible<typename unique_ptr<U, ThatD>::pointer, pointer>::value & &
146 !is_array<U>::value,
147 unique_ptr&> operator=(unique_ptr<U, ThatD>&& that) /*noexcept*/ {
148 reset(that.release());
149 get_deleter() = forward<ThatD>(that.get_deleter());
150 return *this;
151 }
152
153 unique_ptr& operator=(skstd::nullptr_t) /*noexcept*/ {
154 reset();
155 return *this;
156 }
157
158 add_lvalue_reference_t<element_type> operator*() const {
159 SkASSERT(get() != pointer());
160 return *get();
161 }
162
163 pointer operator->() const /*noexcept*/ {
164 SkASSERT(get() != pointer());
165 return get();
166 }
167
168 pointer get() const /*noexcept*/ {
169 return data.getPointer();
170 }
171
172 deleter_type& get_deleter() /*noexcept*/ {
173 return data.getDeleter();
174 }
175
176 const deleter_type& get_deleter() const /*noexcept*/ {
177 return data.getDeleter();
178 }
179
180 //explicit operator bool() const noexcept {
181 bool is_attached() const /*noexcept*/ {
182 return get() == pointer() ? false : true;
183 }
184
185 pointer release() /*noexcept*/ {
186 pointer ptr = get();
187 data.getPointer() = pointer();
188 return ptr;
189 }
190
191 void reset(pointer ptr = pointer()) /*noexcept*/ {
192 SkTSwap(data.getPointer(), ptr);
193 if (ptr != pointer()) {
194 get_deleter()(ptr);
195 }
196 }
197
198 void swap(unique_ptr& that) /*noexcept*/ {
199 SkTSwap(data, that.data);
200 }
201
202 unique_ptr(const unique_ptr&) = delete;
203 unique_ptr& operator=(const unique_ptr&) = delete;
204 };
205
206 template <typename T, typename D> class unique_ptr<T[], D> {
207 // remove_reference_t<D>::pointer if that type exists, otherwise T*.
208 struct pointer_type_detector {
209 template <typename U> static typename U::pointer detector(typename U::po inter*);
210 template <typename U> static T* detector(...);
211 using type = decltype(detector<remove_reference_t<D>>(0));
212 };
213
214 public:
215 using pointer = typename pointer_type_detector::type;
216 using element_type = T;
217 using deleter_type = D;
218
219 private:
220 template <typename B, bool = is_empty<B>::value /*&& !is_final<B>::value*/>
221 struct compressed_base : private B {
222 /*constexpr*/ compressed_base() : B() {}
223 /*constexpr*/ compressed_base(const B& b) : B(b) {}
224 /*constexpr*/ compressed_base(const B&& b) : B(move(b)) {}
225 /*constexpr*/ B& get() /*noexcept*/ { return *this; }
226 /*constexpr*/ B const& get() const /*noexcept*/ { return *this; }
227 void swap(compressed_base&) /*noexcept*/ { }
228 };
229
230 template <typename B> struct compressed_base<B, false> {
231 B fb;
232 /*constexpr*/ compressed_base() : B() {}
233 /*constexpr*/ compressed_base(const B& b) : fb(b) {}
234 /*constexpr*/ compressed_base(const B&& b) : fb(move(b)) {}
235 /*constexpr*/ B& get() /*noexcept*/ { return fb; }
236 /*constexpr*/ B const& get() const /*noexcept*/ { return fb; }
237 void swap(compressed_base& that) /*noexcept*/ { SkTSwap(fb, that.fB); }
238 };
239
240 struct compressed_data : private compressed_base<deleter_type> {
241 pointer fPtr;
242 /*constexpr*/ compressed_data() : compressed_base<deleter_type>(), fPtr( ) {}
243 /*constexpr*/ compressed_data(const pointer& ptr, const deleter_type& d)
244 : compressed_base<deleter_type>(d), fPtr(ptr) {}
245 template <typename U1, typename U2, typename = enable_if_t<
246 is_convertible<U1, pointer>::value && is_convertible<U2, deleter_typ e>::value
247 >> /*constexpr*/ compressed_data(U1&& ptr, U2&& d)
248 : compressed_base<deleter_type>(skstd::forward<U2>(d)), fPtr(skstd:: forward<U1>(ptr)) {}
249 /*constexpr*/ pointer& getPointer() /*noexcept*/ { return fPtr; }
250 /*constexpr*/ pointer const& getPointer() const /*noexcept*/ { return fP tr; }
251 /*constexpr*/ deleter_type& getDeleter() /*noexcept*/ {
252 return compressed_base<deleter_type>::get();
253 }
254 /*constexpr*/ deleter_type const& getDeleter() const /*noexcept*/ {
255 return compressed_base<deleter_type>::get();
256 }
257 void swap(compressed_data& that) /*noexcept*/ {
258 compressed_base<deleter_type>::swap(static_cast<compressed_base<dele ter_type>>(that));
259 SkTSwap(fPtr, that.fPtr);
260 }
261 };
262 compressed_data data;
263
264 public:
265 /*constexpr*/ unique_ptr() /*noexcept*/ : data() {
266 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
267 }
268
269 /*constexpr*/ unique_ptr(skstd::nullptr_t) /*noexcept*/ : unique_ptr() { }
270
271 explicit unique_ptr(pointer ptr) /*noexcept*/ : data(ptr, deleter_type()) {
272 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
273 }
274
275 unique_ptr(pointer ptr,
276 conditional_t<is_reference<deleter_type>::value, deleter_type,con st deleter_type&> d)
277 /*noexcept*/ : data(ptr, d)
278 {}
279
280 unique_ptr(pointer ptr, remove_reference_t<deleter_type>&& d) /*noexcept*/
281 : data(move(ptr), move(d))
282 {
283 static_assert(!is_reference<deleter_type>::value,
284 "Binding an rvalue reference deleter as an lvalue reference deleter is not allowed.");
285 }
286
287 unique_ptr(unique_ptr&& that) /*noexcept*/
288 : data(that.release(), forward<deleter_type>(that.get_deleter()))
289 {}
290
291 ~unique_ptr() {
292 pointer& ptr = data.getPointer();
293 if (ptr != nullptr) {
294 get_deleter()(ptr);
295 }
296 ptr = pointer();
297 }
298
299 unique_ptr& operator=(unique_ptr&& that) /*noexcept*/ {
300 reset(that.release());
301 get_deleter() = forward<deleter_type>(that.get_deleter());
302 return *this;
303 }
304
305 unique_ptr& operator=(skstd::nullptr_t) /*noexcept*/ {
306 reset();
307 return *this;
308 }
309
310 add_lvalue_reference_t<element_type> operator[](size_t i) const {
311 SkASSERT(get() != pointer());
312 return get()[i];
313 }
314
315 pointer get() const /*noexcept*/ {
316 return data.getPointer();
317 }
318
319 deleter_type& get_deleter() /*noexcept*/ {
320 return data.getDeleter();
321 }
322
323 const deleter_type& get_deleter() const /*noexcept*/ {
324 return data.getDeleter();
325 }
326
327 //explicit operator bool() const noexcept {
328 bool is_attached() const /*noexcept*/ {
329 return get() == pointer() ? false : true;
330 }
331
332 pointer release() /*noexcept*/ {
333 pointer ptr = get();
334 data.getPointer() = pointer();
335 return ptr;
336 }
337
338 void reset(pointer ptr = pointer()) /*noexcept*/ {
339 SkTSwap(data.getPointer(), ptr);
340 if (ptr != pointer()) {
341 get_deleter()(ptr);
342 }
343 }
344
345 template <typename U> void reset(U*) = delete;
346
347 void swap(unique_ptr& that) /*noexcept*/ {
348 data.swap(that.data);
349 }
350
351 unique_ptr(const unique_ptr&) = delete;
352 unique_ptr& operator=(const unique_ptr&) = delete;
353 };
354
355 template <typename T, typename D>
356 inline void swap(unique_ptr<T, D>& a, unique_ptr<T, D>& b) /*noexcept*/ {
357 a.swap(b);
358 }
359
360 template <typename T, typename D, typename U, typename ThatD>
361 inline bool operator==(const unique_ptr<T, D>& a, const unique_ptr<U, ThatD>& b) {
362 return a.get() == b.get();
363 }
364
365 template <typename T, typename D>
366 inline bool operator==(const unique_ptr<T, D>& a, skstd::nullptr_t) /*noexcept*/ {
367 //return !a;
368 return !a.is_attached();
369 }
370
371 template <typename T, typename D>
372 inline bool operator==(skstd::nullptr_t, const unique_ptr<T, D>& b) /*noexcept*/ {
373 //return !b;
374 return !b.is_attached();
375 }
376
377 template <typename T, typename D, typename U, typename ThatD>
378 inline bool operator!=(const unique_ptr<T, D>& a, const unique_ptr<U, ThatD>& b) {
379 return a.get() != b.get();
380 }
381
382 template <typename T, typename D>
383 inline bool operator!=(const unique_ptr<T, D>& a, skstd::nullptr_t) /*noexcept*/ {
384 //return (bool)a;
385 return a.is_attached();
386 }
387
388 template <typename T, typename D>
389 inline bool operator!=(skstd::nullptr_t, const unique_ptr<T, D>& b) /*noexcept*/ {
390 //return (bool)b;
391 return b.is_attached();
392 }
393
394 } // namespace skstd
395
396 #endif
OLDNEW
« no previous file with comments | « include/private/SkTemplates.h ('k') | include/private/SkUtility.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698