SkRefCnt.h revision 217c0b3f137d824413e806759bc25378abbe8c18
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkRefCnt_DEFINED 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkRefCnt_DEFINED 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11e6e41a8a19976a822de36379db23184ff2f28601herb#include "../private/SkAtomics.h" 121138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein#include "../private/SkUniquePtr.h" 13f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "SkTypes.h" 14217c0b3f137d824413e806759bc25378abbe8c18halcanary#include <utility> 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 166d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase 176d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 1810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase is the base class for objects that may be shared by multiple 19a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com objects. When an existing owner wants to share a reference, it calls ref(). 20a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com When an owner wants to release its reference, it calls unref(). When the 21a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com shared object's reference count goes to zero as the result of an unref() 22a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com call, its (virtual) destructor is called. It is an error for the 23a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com destructor to be called explicitly (or via the object going out of scope on 24a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the stack or calling delete) if getRefCnt() > 1. 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 26e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SK_API SkRefCntBase : SkNoncopyable { 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Default construct, initializing the reference count to 1. 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase() : fRefCnt(1) {} 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 32a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com /** Destruct, asserting that the reference count is 1. 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com virtual ~SkRefCntBase() { 354c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG 36b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt); 374c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com fRefCnt = 0; // illegal value, to catch us if we reuse after delete 384c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif 394c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com } 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4121180e26519a23cc69f4673f0b518395fddac57bmtklein#ifdef SK_DEBUG 42f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Return the reference count. Use only for debugging. */ 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t getRefCnt() const { return fRefCnt; } 4421180e26519a23cc69f4673f0b518395fddac57bmtklein#endif 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 46ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org /** May return true if the caller is the only owner. 47f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com * Ensures that all previous owner's actions are complete. 48f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com */ 49f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool unique() const { 507b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) { 517b274c78fbeefa3818af68099545f2839c854847mtklein // The acquire barrier is only really needed if we return true. It 527b274c78fbeefa3818af68099545f2839c854847mtklein // prevents code conditioned on the result of unique() from running 537b274c78fbeefa3818af68099545f2839c854847mtklein // until previous owners are all totally done calling unref(). 547b274c78fbeefa3818af68099545f2839c854847mtklein return true; 55f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 567b274c78fbeefa3818af68099545f2839c854847mtklein return false; 57f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 58f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Increment the reference count. Must be balanced by a call to unref(). 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ref() const { 62ab5d5de420503018b385b73e91b24812916c2080djsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 63ab5d5de420503018b385b73e91b24812916c2080djsollen // Android employs some special subclasses that enable the fRefCnt to 64ab5d5de420503018b385b73e91b24812916c2080djsollen // go to zero, but not below, prior to reusing the object. This breaks 65ab5d5de420503018b385b73e91b24812916c2080djsollen // the use of unique() on such objects and as such should be removed 66ab5d5de420503018b385b73e91b24812916c2080djsollen // once the Android code is fixed. 67ab5d5de420503018b385b73e91b24812916c2080djsollen SkASSERT(fRefCnt >= 0); 68ab5d5de420503018b385b73e91b24812916c2080djsollen#else 69f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 70ab5d5de420503018b385b73e91b24812916c2080djsollen#endif 717b274c78fbeefa3818af68099545f2839c854847mtklein (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); // No barrier required. 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Decrement the reference count. If the reference count is 1 before the 75a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com decrement, then delete the object. Note that if this is the case, then 76a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the object needs to have been allocated via new, and not on the stack. 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void unref() const { 79f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 807b274c78fbeefa3818af68099545f2839c854847mtklein // A release here acts in place of all releases we "should" have been doing in ref(). 817b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { 827b274c78fbeefa3818af68099545f2839c854847mtklein // Like unique(), the acquire is only needed on success, to make sure 837b274c78fbeefa3818af68099545f2839c854847mtklein // code in internal_dispose() doesn't happen before the decrement. 847b274c78fbeefa3818af68099545f2839c854847mtklein this->internal_dispose(); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8803087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG 897f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com void validate() const { 90f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 917f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 9203087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif 937f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 94f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 95f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 96f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Allow subclasses to call this if they've overridden internal_dispose 97f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * so they can reset fRefCnt before the destructor is called. Should only 98f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * be called right before calling through to inherited internal_dispose() 99f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * or before calling the destructor. 100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 101f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com void internal_dispose_restore_refcnt_to_1() const { 102a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG 103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkASSERT(0 == fRefCnt); 104a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com fRefCnt = 1; 105a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif 106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 108f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 109f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 110f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Called when the ref count goes to 0. 111f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 112f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const { 113f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 114385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary delete this; 115a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com } 11615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 117f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // The following friends are those which override internal_dispose() 118f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // and conditionally call SkRefCnt::internal_dispose(). 119a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com friend class SkWeakRefCnt; 120a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable int32_t fRefCnt; 1224d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com 12310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com typedef SkNoncopyable INHERITED; 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12610ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE 12710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt. 12810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase. 12910ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE 13010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else 13110ba006631a0c350aa2bcba188a60404869607c8bungeman@google.comclass SK_API SkRefCnt : public SkRefCntBase { }; 13210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#endif 13310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com 1347f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1357f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1367f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1377f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com null in on each side of the assignment, and ensuring that ref() is called 1387f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com before unref(), in case the two pointers point to the same object. 1397f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1407f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src) \ 1417f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com do { \ 1427f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (src) src->ref(); \ 1437f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (dst) dst->unref(); \ 1447f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com dst = src; \ 1457f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } while (0) 1467f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1477f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 14877a53de20d723ca21cc824fd97e68aaa60e022eabungeman/** Call obj->ref() and return obj. The obj must not be nullptr. 1497f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1501fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) { 1511fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com SkASSERT(obj); 1521fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com obj->ref(); 1531fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1541fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com} 1551fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com 1561fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj. 1571fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */ 1581fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) { 1597f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1607f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->ref(); 1617f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1621fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1637f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref() 1667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) { 1687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->unref(); 1707f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1727f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 173a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) { 17449f085dddff10473b6ebf832a974288300224e60bsalomon if (obj) { 175a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj->unref(); 17677a53de20d723ca21cc824fd97e68aaa60e022eabungeman obj = nullptr; 177a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org } 178a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org} 179a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org 1807f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1817f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 18277a53de20d723ca21cc824fd97e68aaa60e022eabungemantemplate <typename T> struct SkTUnref { 18377a53de20d723ca21cc824fd97e68aaa60e022eabungeman void operator()(T* t) { t->unref(); } 18477a53de20d723ca21cc824fd97e68aaa60e022eabungeman}; 18577a53de20d723ca21cc824fd97e68aaa60e022eabungeman 186a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/** 18791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com * Utility class that simply unref's its argument in the destructor. 188a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 1891138be45eac9dd21b094c9774a6f9c612f9f8fa8mtkleintemplate <typename T> class SkAutoTUnref : public skstd::unique_ptr<T, SkTUnref<T>> { 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1911138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein explicit SkAutoTUnref(T* obj = nullptr) : skstd::unique_ptr<T, SkTUnref<T>>(obj) {} 1921dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com 1931138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein T* detach() { return this->release(); } 1941138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein operator T*() const { return this->get(); } 195a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com}; 196e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( 197a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 198a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 199a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic: 200a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 202e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16. 20508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// There's only benefit to using this if the deriving class does not otherwise need a vtable. 20608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleintemplate <typename Derived> 20708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinclass SkNVRefCnt : SkNoncopyable { 20808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinpublic: 20908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein SkNVRefCnt() : fRefCnt(1) {} 2103c850c561fcad1ac35bff4ec2875a40ef2309148reed ~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); } 21108d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 21208d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same: 21308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unique() needs acquire when it returns true, and no barrier if it returns false; 21408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - ref() doesn't need any barrier; 21508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unref() needs a release barrier, and an acquire if it's going to call delete. 21608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 2177b274c78fbeefa3818af68099545f2839c854847mtklein bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); } 2187b274c78fbeefa3818af68099545f2839c854847mtklein void ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); } 21990d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed void unref() const { 2207b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { 221385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's assert 22297466ab03e025b6edd94c4f0f369cd0b0d8c3319mtklein delete (const Derived*)this; 22390d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 22490d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 2257b274c78fbeefa3818af68099545f2839c854847mtklein void deref() const { this->unref(); } 226844aa334a43a95cd83a27d565db1d3370d8dc10cFlorin Malita 22708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinprivate: 22808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein mutable int32_t fRefCnt; 22908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein}; 23008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 231bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/////////////////////////////////////////////////////////////////////////////////////////////////// 232bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 233bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/** 234bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shared pointer class to wrap classes that support a ref()/unref() interface. 235bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * 236bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * This can be used for classes inheriting from SkRefCnt, but it also works for other 237bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * classes that match the interface, but have different internal choices: e.g. the hosted class 238bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp. 239bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 240bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedtemplate <typename T> class sk_sp { 241bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic: 242bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp() : fPtr(nullptr) {} 243bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(std::nullptr_t) : fPtr(nullptr) {} 244bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 245bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 246bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shares the underlying object by calling ref(), so that both the argument and the newly 247bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * created sk_sp both have a reference to it. 248bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 249bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} 250bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 251bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 252bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Move the underlying object from the argument to the newly created sk_sp. Afterwards only 253bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * the new sk_sp will have a reference to the object, and the argument will point to null. 254bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() or unref() will be made. 255bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 256bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} 257bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 258bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 259bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Adopt the bare pointer into the newly created sk_sp. 260bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() or unref() will be made. 261bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 262bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed explicit sk_sp(T* obj) : fPtr(obj) {} 263bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 264bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 265bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Calls unref() on the underlying object pointer. 266bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 267bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed ~sk_sp() { 268bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed SkSafeUnref(fPtr); 269bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 270bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 271bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(std::nullptr_t) { this->reset(); } 272bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 273bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 274bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shares the underlying object referenced by the argument by calling ref() on it. If this 275bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that 276bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * object. 277bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 278bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(const sk_sp<T>& that) { 279bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed this->reset(SkSafeRef(that.get())); 280bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return *this; 281bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 282bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 283bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 284bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held 285bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * a reference to another object, unref() will be called on that object. No call to ref() 286bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * will be made. 287bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 288bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(sk_sp<T>&& that) { 289bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed this->reset(that.release()); 290bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return *this; 291bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 292bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 293bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed bool operator==(std::nullptr_t) const { return this->get() == nullptr; } 294bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed bool operator!=(std::nullptr_t) const { return this->get() != nullptr; } 295bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 296bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed bool operator==(const sk_sp<T>& that) const { return this->get() == that.get(); } 297bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed bool operator!=(const sk_sp<T>& that) const { return this->get() != that.get(); } 298bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 299bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed explicit operator bool() const { return this->get() != nullptr; } 300bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 301bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* get() const { return fPtr; } 302bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* operator->() const { return fPtr; } 303bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 304bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 305bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Adopt the new bare pointer, and call unref() on any previously held object (if not null). 306bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() will be made. 307bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 308bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed void reset(T* ptr = nullptr) { 309bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed if (fPtr != ptr) { 310bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed SkSafeUnref(fPtr); 311bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed fPtr = ptr; 312bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 313bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 314bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 315bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 316bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Return the bare pointer, and set the internal object pointer to nullptr. 317bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * The caller must assume ownership of the object, and manage its reference count directly. 318bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to unref() will be made. 319bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 320bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* SK_WARN_UNUSED_RESULT release() { 321bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* ptr = fPtr; 322bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed fPtr = nullptr; 323bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return ptr; 324bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 325bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 326bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedprivate: 327bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* fPtr; 328bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed}; 329bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 330217c0b3f137d824413e806759bc25378abbe8c18halcanarytemplate <typename T, typename... Args> 331217c0b3f137d824413e806759bc25378abbe8c18halcanarysk_sp<T> sk_make_sp(Args&&... args) { 332217c0b3f137d824413e806759bc25378abbe8c18halcanary return sk_sp<T>(new T(std::forward<Args>(args)...)); 333217c0b3f137d824413e806759bc25378abbe8c18halcanary} 334217c0b3f137d824413e806759bc25378abbe8c18halcanary 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 336