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 |