| 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) { |
| 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 |