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

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: Test should clean up after itself. 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*/ {}
mtklein 2015/09/04 13:25:42 funky indent?
bungeman-skia 2015/09/04 19:20:19 Done. Got carried away indenting things.
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 void swap(compressed_base&) /*noexcept*/ { }
56 /*constexpr*/ B& get() /*noexcept*/ { return *this; }
57 /*constexpr*/ B const& get() const /*noexcept*/ { return *this; }
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 void swap(compressed_base& that) /*noexcept*/ { SkTSwap(fb, that.fB); }
66 /*constexpr*/ B& get() /*noexcept*/ { return fb; }
67 /*constexpr*/ B const& get() const /*noexcept*/ { return 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*/
78 compressed_data(U1&& ptr, U2&& d)
79 : compressed_base<deleter_type>(skstd::forward<U2>(d)), fPtr(skstd:: forward<U1>(ptr)) {}
80 void swap(compressed_data& that) /*noexcept*/ {
81 compressed_base<deleter_type>::swap(static_cast<compressed_base<dele ter_type>>(that));
82 SkTSwap(fPtr, that.fPtr);
83 }
84 /*constexpr*/ pointer& getPointer() /*noexcept*/ { return fPtr; }
85 /*constexpr*/ pointer const& getPointer() const /*noexcept*/ { return fP tr; }
86 /*constexpr*/ deleter_type& getDeleter() /*noexcept*/ {
87 return compressed_base<deleter_type>::get();
88 }
89 /*constexpr*/ deleter_type const& getDeleter() const /*noexcept*/ {
90 return compressed_base<deleter_type>::get();
91 }
92 };
93 compressed_data data;
94
95 public:
96 /*constexpr*/ unique_ptr() /*noexcept*/ : data() {
97 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
98 }
99
100 /*constexpr*/ unique_ptr(skstd::nullptr_t) /*noexcept*/ : unique_ptr() { }
101
102 explicit unique_ptr(pointer ptr) /*noexcept*/ : data(ptr, deleter_type()) {
103 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
104 }
105
106 unique_ptr(pointer ptr,
107 conditional_t<is_reference<deleter_type>::value, deleter_type,con st deleter_type&> d)
108 /*noexcept*/ : data(ptr, d)
109 { }
110
111 unique_ptr(pointer ptr, remove_reference_t<deleter_type>&& d) /*noexcept*/
112 : data(move(ptr), move(d))
113 {
114 static_assert(!is_reference<deleter_type>::value,
115 "Binding an rvalue reference deleter as an lvalue reference deleter is not allowed.");
116 }
117
118
119 unique_ptr(unique_ptr&& that) /*noexcept*/
120 : data(that.release(), forward<deleter_type>(that.get_deleter()))
121 { }
122
123 template <typename U, typename ThatD, typename = enable_if_t<
124 is_convertible<typename unique_ptr<U, ThatD>::pointer, pointer>::value & &
125 !is_array<U>::value &&
126 conditional_t<is_reference<D>::value, is_same<ThatD, D>, is_convertible< ThatD, D>>::value>>
127 unique_ptr(unique_ptr<U, ThatD>&& that) /*noexcept*/
128 : data(that.release(), forward<ThatD>(that.get_deleter()))
129 { }
130
131 ~unique_ptr() /*noexcept*/ {
132 pointer& ptr = data.getPointer();
133 if (ptr != nullptr) {
134 get_deleter()(ptr);
135 }
136 ptr = pointer();
137 }
138
139 unique_ptr& operator=(unique_ptr&& that) /*noexcept*/ {
140 reset(that.release());
141 get_deleter() = forward<deleter_type>(that.get_deleter());
142 return *this;
143 }
144
145 template <typename U, typename ThatD> enable_if_t<
146 is_convertible<typename unique_ptr<U, ThatD>::pointer, pointer>::value & &
147 !is_array<U>::value,
148 unique_ptr&> operator=(unique_ptr<U, ThatD>&& that) /*noexcept*/ {
149 reset(that.release());
150 get_deleter() = forward<ThatD>(that.get_deleter());
151 return *this;
152 }
153
154 unique_ptr& operator=(skstd::nullptr_t) /*noexcept*/ {
155 reset();
156 return *this;
157 }
158
159 add_lvalue_reference_t<element_type> operator*() const {
160 SkASSERT(get() != pointer());
161 return *get();
162 }
163
164 pointer operator->() const /*noexcept*/ {
165 SkASSERT(get() != pointer());
166 return get();
167 }
168
169 pointer get() const /*noexcept*/ {
170 return data.getPointer();
171 }
172
173 deleter_type& get_deleter() /*noexcept*/ {
174 return data.getDeleter();
175 }
176
177 const deleter_type& get_deleter() const /*noexcept*/ {
178 return data.getDeleter();
179 }
180
181 //explicit operator bool() const noexcept {
mtklein 2015/09/04 13:25:42 what happened here?
bungeman-skia 2015/09/04 19:20:19 I don't want to use 'explicit operator' yet becaus
182 bool is_attached() const /*noexcept*/ {
183 return get() == pointer() ? false : true;
184 }
185
186 pointer release() /*noexcept*/ {
187 pointer ptr = get();
188 data.getPointer() = pointer();
189 return ptr;
190 }
191
192 void reset(pointer ptr = pointer()) /*noexcept*/ {
193 SkTSwap(data.getPointer(), ptr);
194 if (ptr != pointer()) {
195 get_deleter()(ptr);
196 }
197 }
198
199 void swap(unique_ptr& that) /*noexcept*/ {
200 SkTSwap(data, that.data);
201 }
202
203 unique_ptr(const unique_ptr&) = delete;
204 unique_ptr& operator=(const unique_ptr&) = delete;
205 };
206
207 template <typename T, typename D> class unique_ptr<T[], D> {
208 // remove_reference_t<D>::pointer if that type exists, otherwise T*.
209 struct pointer_type_detector {
210 template <typename U> static typename U::pointer detector(typename U::po inter*);
211 template <typename U> static T* detector(...);
212 using type = decltype(detector<remove_reference_t<D>>(0));
213 };
214
215 public:
216 using pointer = typename pointer_type_detector::type;
217 using element_type = T;
218 using deleter_type = D;
219
220 private:
221 template <typename B, bool = is_empty<B>::value /*&& !is_final<B>::value*/>
222 struct compressed_base : private B {
223 /*constexpr*/ compressed_base() : B() {}
224 /*constexpr*/ compressed_base(const B& b) : B(b) {}
225 /*constexpr*/ compressed_base(const B&& b) : B(move(b)) {}
226 void swap(compressed_base&) /*noexcept*/ { }
227 /*constexpr*/ B& get() /*noexcept*/ { return *this; }
228 /*constexpr*/ B const& get() const /*noexcept*/ { return *this; }
229 };
230
231 template <typename B> struct compressed_base<B, false> {
232 B fb;
233 /*constexpr*/ compressed_base() : B() {}
234 /*constexpr*/ compressed_base(const B& b) : fb(b) {}
235 /*constexpr*/ compressed_base(const B&& b) : fb(move(b)) {}
236 void swap(compressed_base& that) /*noexcept*/ { SkTSwap(fb, that.fB); }
237 /*constexpr*/ B& get() /*noexcept*/ { return fb; }
238 /*constexpr*/ B const& get() const /*noexcept*/ { return fb; }
239 };
240
241 struct compressed_data : private compressed_base<deleter_type> {
242 pointer fPtr;
243 /*constexpr*/ compressed_data() : compressed_base<deleter_type>(), fPtr( ) {}
244 /*constexpr*/ compressed_data(const pointer& ptr, const deleter_type& d)
245 : compressed_base<deleter_type>(d), fPtr(ptr) {}
246 template <typename U1, typename U2, typename = enable_if_t<
247 is_convertible<U1, pointer>::value && is_convertible<U2, deleter_typ e>::value
248 >> /*constexpr*/
249 compressed_data(U1&& ptr, U2&& d)
250 : compressed_base<deleter_type>(skstd::forward<U2>(d)), fPtr(skstd:: forward<U1>(ptr)) {}
251 void swap(compressed_data& that) /*noexcept*/ {
252 compressed_base<deleter_type>::swap(static_cast<compressed_base<dele ter_type>>(that));
253 SkTSwap(fPtr, that.fPtr);
254 }
255 /*constexpr*/ pointer& getPointer() /*noexcept*/ { return fPtr; }
256 /*constexpr*/ pointer const& getPointer() const /*noexcept*/ { return fP tr; }
257 /*constexpr*/ deleter_type& getDeleter() /*noexcept*/ {
258 return compressed_base<deleter_type>::get();
259 }
260 /*constexpr*/ deleter_type const& getDeleter() const /*noexcept*/ {
261 return compressed_base<deleter_type>::get();
262 }
263 };
264 compressed_data data;
265
266 public:
267 /*constexpr*/ unique_ptr() /*noexcept*/ : data() {
268 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
269 }
270
271 /*constexpr*/ unique_ptr(skstd::nullptr_t) /*noexcept*/ : unique_ptr() { }
272
273 explicit unique_ptr(pointer ptr) /*noexcept*/ : data(ptr, deleter_type()) {
274 static_assert(!is_pointer<deleter_type>::value, "Deleter is nullptr func tion pointer!");
275 }
276
277 unique_ptr(pointer ptr,
278 conditional_t<is_reference<deleter_type>::value, deleter_type,con st deleter_type&> d)
279 /*noexcept*/ : data(ptr, d)
280 {}
281
282 unique_ptr(pointer ptr, remove_reference_t<deleter_type>&& d) /*noexcept*/
283 : data(move(ptr), move(d))
284 {
285 static_assert(!is_reference<deleter_type>::value,
286 "Binding an rvalue reference deleter as an lvalue reference deleter is not allowed.");
287 }
288
289 unique_ptr(unique_ptr&& that) /*noexcept*/
290 : data(that.release(), forward<deleter_type>(that.get_deleter()))
291 {}
292
293 ~unique_ptr() {
294 pointer& ptr = data.getPointer();
295 if (ptr != nullptr) {
296 get_deleter()(ptr);
297 }
298 ptr = pointer();
299 }
300
301 unique_ptr& operator=(unique_ptr&& that) /*noexcept*/ {
302 reset(that.release());
303 get_deleter() = forward<deleter_type>(that.get_deleter());
304 return *this;
305 }
306
307 unique_ptr& operator=(skstd::nullptr_t) /*noexcept*/ {
308 reset();
309 return *this;
310 }
311
312 add_lvalue_reference_t<element_type> operator[](size_t i) const {
313 SkASSERT(get() != pointer());
314 return get()[i];
315 }
316
317 pointer get() const /*noexcept*/ {
318 return data.getPointer();
319 }
320
321 deleter_type& get_deleter() /*noexcept*/ {
322 return data.getDeleter();
323 }
324
325 const deleter_type& get_deleter() const /*noexcept*/ {
326 return data.getDeleter();
327 }
328
329 //explicit operator bool() const noexcept {
330 bool is_attached() const /*noexcept*/ {
331 return get() == pointer() ? false : true;
332 }
333
334 pointer release() /*noexcept*/ {
335 pointer ptr = get();
336 data.getPointer() = pointer();
337 return ptr;
338 }
339
340 void reset(pointer ptr = pointer()) /*noexcept*/ {
341 SkTSwap(data.getPointer(), ptr);
342 if (ptr != pointer()) {
343 get_deleter()(ptr);
344 }
345 }
346
347 template <typename U> void reset(U*) = delete;
348
349 void swap(unique_ptr& that) /*noexcept*/ {
350 data.swap(that.data);
351 }
352
353 unique_ptr(const unique_ptr&) = delete;
354 unique_ptr& operator=(const unique_ptr&) = delete;
355 };
356
357 template <typename T, typename D>
358 inline void swap(unique_ptr<T, D>& a, unique_ptr<T, D>& b) /*noexcept*/ {
359 a.swap(b);
360 }
361
362 template <typename T, typename D, typename U, typename ThatD>
363 inline bool operator==(const unique_ptr<T, D>& a, const unique_ptr<U, ThatD>& b) {
364 return a.get() == b.get();
365 }
366
367 template <typename T, typename D>
368 inline bool operator==(const unique_ptr<T, D>& a, skstd::nullptr_t) /*noexcept*/ {
369 //return !a;
370 return !a.is_attached();
371 }
372
373 template <typename T, typename D>
374 inline bool operator==(skstd::nullptr_t, const unique_ptr<T, D>& b) /*noexcept*/ {
375 //return !b;
376 return !b.is_attached();
377 }
378
379 template <typename T, typename D, typename U, typename ThatD>
380 inline bool operator!=(const unique_ptr<T, D>& a, const unique_ptr<U, ThatD>& b) {
381 return a.get() != b.get();
382 }
383
384 template <typename T, typename D>
385 inline bool operator!=(const unique_ptr<T, D>& a, skstd::nullptr_t) /*noexcept*/ {
386 //return (bool)a;
387 return a.is_attached();
388 }
389
390 template <typename T, typename D>
391 inline bool operator!=(skstd::nullptr_t, const unique_ptr<T, D>& b) /*noexcept*/ {
392 //return (bool)b;
393 return b.is_attached();
394 }
395
396 } // namespace skstd
397
398 #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