OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkRefCnt_DEFINED | 8 #ifndef SkRefCnt_DEFINED |
9 #define SkRefCnt_DEFINED | 9 #define SkRefCnt_DEFINED |
10 | 10 |
11 #include "../private/SkAtomics.h" | 11 #include "../private/SkAtomics.h" |
12 #include "../private/SkUniquePtr.h" | 12 #include "../private/SkUniquePtr.h" |
13 #include "SkTypes.h" | 13 #include "SkTypes.h" |
14 #include <functional> | |
14 #include <utility> | 15 #include <utility> |
15 | 16 |
16 /** \class SkRefCntBase | 17 /** \class SkRefCntBase |
17 | 18 |
18 SkRefCntBase is the base class for objects that may be shared by multiple | 19 SkRefCntBase is the base class for objects that may be shared by multiple |
19 objects. When an existing owner wants to share a reference, it calls ref(). | 20 objects. When an existing owner wants to share a reference, it calls ref(). |
20 When an owner wants to release its reference, it calls unref(). When the | 21 When an owner wants to release its reference, it calls unref(). When the |
21 shared object's reference count goes to zero as the result of an unref() | 22 shared object's reference count goes to zero as the result of an unref() |
22 call, its (virtual) destructor is called. It is an error for the | 23 call, its (virtual) destructor is called. It is an error for the |
23 destructor to be called explicitly (or via the object going out of scope on | 24 destructor to be called explicitly (or via the object going out of scope on |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
234 * Shared pointer class to wrap classes that support a ref()/unref() interface. | 235 * Shared pointer class to wrap classes that support a ref()/unref() interface. |
235 * | 236 * |
236 * This can be used for classes inheriting from SkRefCnt, but it also works for other | 237 * This can be used for classes inheriting from SkRefCnt, but it also works for other |
237 * classes that match the interface, but have different internal choices: e.g. the hosted class | 238 * classes that match the interface, but have different internal choices: e.g. the hosted class |
238 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk _sp. | 239 * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk _sp. |
239 */ | 240 */ |
240 template <typename T> class sk_sp { | 241 template <typename T> class sk_sp { |
241 /** Supports safe bool idiom. Obsolete with explicit operator bool. */ | 242 /** Supports safe bool idiom. Obsolete with explicit operator bool. */ |
242 using unspecified_bool_type = T* sk_sp::*; | 243 using unspecified_bool_type = T* sk_sp::*; |
243 public: | 244 public: |
245 using element_type = T; | |
246 | |
244 sk_sp() : fPtr(nullptr) {} | 247 sk_sp() : fPtr(nullptr) {} |
245 sk_sp(std::nullptr_t) : fPtr(nullptr) {} | 248 sk_sp(std::nullptr_t) : fPtr(nullptr) {} |
246 | 249 |
247 /** | 250 /** |
248 * Shares the underlying object by calling ref(), so that both the argument and the newly | 251 * Shares the underlying object by calling ref(), so that both the argument and the newly |
249 * created sk_sp both have a reference to it. | 252 * created sk_sp both have a reference to it. |
250 */ | 253 */ |
251 sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} | 254 sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} |
252 template <typename U, | 255 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>> |
253 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >> | |
254 sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {} | 256 sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {} |
255 | 257 |
256 /** | 258 /** |
257 * Move the underlying object from the argument to the newly created sk_sp. Afterwards only | 259 * Move the underlying object from the argument to the newly created sk_sp. Afterwards only |
258 * the new sk_sp will have a reference to the object, and the argument will point to null. | 260 * the new sk_sp will have a reference to the object, and the argument will point to null. |
259 * No call to ref() or unref() will be made. | 261 * No call to ref() or unref() will be made. |
260 */ | 262 */ |
261 sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} | 263 sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} |
262 template <typename U, | 264 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>> |
263 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >> | |
264 sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {} | 265 sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {} |
265 | 266 |
266 /** | 267 /** |
267 * Adopt the bare pointer into the newly created sk_sp. | 268 * Adopt the bare pointer into the newly created sk_sp. |
268 * No call to ref() or unref() will be made. | 269 * No call to ref() or unref() will be made. |
269 */ | 270 */ |
270 explicit sk_sp(T* obj) : fPtr(obj) {} | 271 explicit sk_sp(T* obj) : fPtr(obj) {} |
271 | 272 |
272 /** | 273 /** |
273 * Calls unref() on the underlying object pointer. | 274 * Calls unref() on the underlying object pointer. |
274 */ | 275 */ |
275 ~sk_sp() { | 276 ~sk_sp() { |
276 SkSafeUnref(fPtr); | 277 SkSafeUnref(fPtr); |
278 SkDEBUGCODE(fPtr = nullptr); | |
277 } | 279 } |
278 | 280 |
279 sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; } | 281 sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; } |
280 | 282 |
281 /** | 283 /** |
282 * Shares the underlying object referenced by the argument by calling ref() on it. If this | 284 * Shares the underlying object referenced by the argument by calling ref() on it. If this |
283 * sk_sp previously had a reference to an object (i.e. not null) it will ca ll unref() on that | 285 * sk_sp previously had a reference to an object (i.e. not null) it will ca ll unref() on that |
284 * object. | 286 * object. |
285 */ | 287 */ |
286 sk_sp<T>& operator=(const sk_sp<T>& that) { | 288 sk_sp<T>& operator=(const sk_sp<T>& that) { |
287 this->reset(SkSafeRef(that.get())); | 289 this->reset(SkSafeRef(that.get())); |
288 return *this; | 290 return *this; |
289 } | 291 } |
290 template <typename U, | 292 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>> |
291 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >> | |
292 sk_sp<T>& operator=(const sk_sp<U>& that) { | 293 sk_sp<T>& operator=(const sk_sp<U>& that) { |
293 this->reset(SkSafeRef(that.get())); | 294 this->reset(SkSafeRef(that.get())); |
294 return *this; | 295 return *this; |
295 } | 296 } |
296 | 297 |
297 /** | 298 /** |
298 * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held | 299 * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held |
299 * a reference to another object, unref() will be called on that object. No call to ref() | 300 * a reference to another object, unref() will be called on that object. No call to ref() |
300 * will be made. | 301 * will be made. |
301 */ | 302 */ |
302 sk_sp<T>& operator=(sk_sp<T>&& that) { | 303 sk_sp<T>& operator=(sk_sp<T>&& that) { |
303 this->reset(that.release()); | 304 this->reset(that.release()); |
304 return *this; | 305 return *this; |
305 } | 306 } |
306 template <typename U, | 307 template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U* , T*>::value>> |
307 typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value >> | |
308 sk_sp<T>& operator=(sk_sp<U>&& that) { | 308 sk_sp<T>& operator=(sk_sp<U>&& that) { |
309 this->reset(that.release()); | 309 this->reset(that.release()); |
310 return *this; | 310 return *this; |
311 } | 311 } |
312 | 312 |
313 bool operator==(std::nullptr_t) const { return this->get() == nullptr; } | |
314 bool operator!=(std::nullptr_t) const { return this->get() != nullptr; } | |
315 | |
316 template <typename U> | |
317 bool operator==(const sk_sp<U>& that) const { return this->get() == that.get (); } | |
318 template <typename U> | |
319 bool operator!=(const sk_sp<U>& that) const { return this->get() != that.get (); } | |
320 | |
321 T& operator*() const { | 313 T& operator*() const { |
322 SkASSERT(this->get() != nullptr); | 314 SkASSERT(this->get() != nullptr); |
323 return *this->get(); | 315 return *this->get(); |
324 } | 316 } |
325 | 317 |
326 // MSVC 2013 does not work correctly with explicit operator bool. | 318 // MSVC 2013 does not work correctly with explicit operator bool. |
327 // https://chromium-cpp.appspot.com/#core-blacklist | 319 // https://chromium-cpp.appspot.com/#core-blacklist |
328 // When explicit operator bool can be used, remove operator! and operator un specified_bool_type. | 320 // When explicit operator bool can be used, remove operator! and operator un specified_bool_type. |
329 //explicit operator bool() const { return this->get() != nullptr; } | 321 //explicit operator bool() const { return this->get() != nullptr; } |
330 operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; } | 322 operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; } |
331 bool operator!() const { return this->get() == nullptr; } | 323 bool operator!() const { return this->get() == nullptr; } |
332 | 324 |
333 T* get() const { return fPtr; } | 325 T* get() const { return fPtr; } |
334 T* operator->() const { return fPtr; } | 326 T* operator->() const { return fPtr; } |
335 | 327 |
336 /** | 328 /** |
337 * Adopt the new bare pointer, and call unref() on any previously held obje ct (if not null). | 329 * Adopt the new bare pointer, and call unref() on any previously held obje ct (if not null). |
338 * No call to ref() will be made. | 330 * No call to ref() will be made. |
339 */ | 331 */ |
340 void reset(T* ptr = nullptr) { | 332 void reset(T* ptr = nullptr) { |
bungeman-skia
2016/03/07 20:07:54
At the very least, Chromium went through a lot of
| |
341 SkSafeUnref(fPtr); | 333 // Calling fPtr->unref() may call this->~() or this->reset(T*). |
334 // http://wg21.cmeerw.net/lwg/issue998 | |
335 // http://wg21.cmeerw.net/lwg/issue2262 | |
336 T* oldPtr = fPtr; | |
342 fPtr = ptr; | 337 fPtr = ptr; |
338 SkSafeUnref(oldPtr); | |
343 } | 339 } |
344 | 340 |
345 /** | 341 /** |
346 * Return the bare pointer, and set the internal object pointer to nullptr. | 342 * Return the bare pointer, and set the internal object pointer to nullptr. |
347 * The caller must assume ownership of the object, and manage its reference count directly. | 343 * The caller must assume ownership of the object, and manage its reference count directly. |
348 * No call to unref() will be made. | 344 * No call to unref() will be made. |
349 */ | 345 */ |
350 T* SK_WARN_UNUSED_RESULT release() { | 346 T* SK_WARN_UNUSED_RESULT release() { |
351 T* ptr = fPtr; | 347 T* ptr = fPtr; |
352 fPtr = nullptr; | 348 fPtr = nullptr; |
353 return ptr; | 349 return ptr; |
354 } | 350 } |
355 | 351 |
352 void swap(sk_sp<T>& that) /*noexcept*/ { | |
353 using std::swap; | |
354 swap(fPtr, that.fPtr); | |
355 } | |
356 | |
356 private: | 357 private: |
357 T* fPtr; | 358 T* fPtr; |
358 }; | 359 }; |
359 | 360 |
361 template <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ { | |
362 a.swap(b); | |
363 } | |
364 | |
365 template <typename T, typename U> inline bool operator==(const sk_sp<T>& a, cons t sk_sp<U>& b) { | |
366 return a.get() == b.get(); | |
367 } | |
368 template <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { | |
369 return !a; | |
370 } | |
371 template <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { | |
372 return !b; | |
373 } | |
374 | |
375 template <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, cons t sk_sp<U>& b) { | |
376 return a.get() != b.get(); | |
377 } | |
378 template <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { | |
379 return static_cast<bool>(a); | |
380 } | |
381 template <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { | |
382 return static_cast<bool>(b); | |
383 } | |
384 | |
385 template <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) { | |
386 // Provide defined total order on sk_sp. | |
387 // http://wg21.cmeerw.net/lwg/issue1297 | |
388 // http://wg21.cmeerw.net/lwg/issue1401 . | |
389 return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get()); | |
390 } | |
391 template <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) { | |
392 return std::less<T*>()(a.get(), nullptr); | |
393 } | |
394 template <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) { | |
395 return std::less<T*>()(nullptr, b.get()); | |
396 } | |
397 | |
398 template <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, cons t sk_sp<U>& b) { | |
399 return !(b < a); | |
400 } | |
401 template <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) { | |
402 return !(nullptr < a); | |
403 } | |
404 template <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) { | |
405 return !(b < nullptr); | |
406 } | |
407 | |
408 template <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) { | |
409 return b < a; | |
410 } | |
411 template <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) { | |
412 return nullptr < a; | |
413 } | |
414 template <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) { | |
415 return b < nullptr; | |
416 } | |
417 | |
418 template <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, cons t sk_sp<U>& b) { | |
419 return !(a < b); | |
420 } | |
421 template <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) { | |
422 return !(a < nullptr); | |
423 } | |
424 template <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) { | |
425 return !(nullptr < b); | |
426 } | |
427 | |
360 template <typename T, typename... Args> | 428 template <typename T, typename... Args> |
361 sk_sp<T> sk_make_sp(Args&&... args) { | 429 sk_sp<T> sk_make_sp(Args&&... args) { |
362 return sk_sp<T>(new T(std::forward<Args>(args)...)); | 430 return sk_sp<T>(new T(std::forward<Args>(args)...)); |
363 } | 431 } |
364 | 432 |
365 #endif | 433 #endif |
OLD | NEW |