SkRefCnt.h revision 5f939ab658a228dce34a3b14a545638407150b92
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" 125f939ab658a228dce34a3b14a545638407150b92mtklein#include "../private/SkTLogic.h" 13f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "SkTypes.h" 14c901c11549acd19e7fc225276f78374ac1600496bungeman#include <functional> 155f939ab658a228dce34a3b14a545638407150b92mtklein#include <memory> 16217c0b3f137d824413e806759bc25378abbe8c18halcanary#include <utility> 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18647cc8474828202c98d540f799742e3074a2aacereed#define SK_SUPPORT_TRANSITION_TO_SP_INTERFACES 19647cc8474828202c98d540f799742e3074a2aacereed 206d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase 216d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 2210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase is the base class for objects that may be shared by multiple 23a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com objects. When an existing owner wants to share a reference, it calls ref(). 24a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com When an owner wants to release its reference, it calls unref(). When the 25a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com shared object's reference count goes to zero as the result of an unref() 26a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com call, its (virtual) destructor is called. It is an error for the 27a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com destructor to be called explicitly (or via the object going out of scope on 28a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the stack or calling delete) if getRefCnt() > 1. 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 30e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SK_API SkRefCntBase : SkNoncopyable { 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Default construct, initializing the reference count to 1. 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase() : fRefCnt(1) {} 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 36a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com /** Destruct, asserting that the reference count is 1. 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com virtual ~SkRefCntBase() { 394c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG 40b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt); 414c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com fRefCnt = 0; // illegal value, to catch us if we reuse after delete 424c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif 434c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com } 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4521180e26519a23cc69f4673f0b518395fddac57bmtklein#ifdef SK_DEBUG 46f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Return the reference count. Use only for debugging. */ 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t getRefCnt() const { return fRefCnt; } 4821180e26519a23cc69f4673f0b518395fddac57bmtklein#endif 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 50ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org /** May return true if the caller is the only owner. 51f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com * Ensures that all previous owner's actions are complete. 52f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com */ 53f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool unique() const { 547b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) { 557b274c78fbeefa3818af68099545f2839c854847mtklein // The acquire barrier is only really needed if we return true. It 567b274c78fbeefa3818af68099545f2839c854847mtklein // prevents code conditioned on the result of unique() from running 577b274c78fbeefa3818af68099545f2839c854847mtklein // until previous owners are all totally done calling unref(). 587b274c78fbeefa3818af68099545f2839c854847mtklein return true; 59f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 607b274c78fbeefa3818af68099545f2839c854847mtklein return false; 61f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 62f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Increment the reference count. Must be balanced by a call to unref(). 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ref() const { 66ab5d5de420503018b385b73e91b24812916c2080djsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 67ab5d5de420503018b385b73e91b24812916c2080djsollen // Android employs some special subclasses that enable the fRefCnt to 68ab5d5de420503018b385b73e91b24812916c2080djsollen // go to zero, but not below, prior to reusing the object. This breaks 69ab5d5de420503018b385b73e91b24812916c2080djsollen // the use of unique() on such objects and as such should be removed 70ab5d5de420503018b385b73e91b24812916c2080djsollen // once the Android code is fixed. 71ab5d5de420503018b385b73e91b24812916c2080djsollen SkASSERT(fRefCnt >= 0); 72ab5d5de420503018b385b73e91b24812916c2080djsollen#else 73f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 74ab5d5de420503018b385b73e91b24812916c2080djsollen#endif 757b274c78fbeefa3818af68099545f2839c854847mtklein (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); // No barrier required. 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Decrement the reference count. If the reference count is 1 before the 79a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com decrement, then delete the object. Note that if this is the case, then 80a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the object needs to have been allocated via new, and not on the stack. 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void unref() const { 83f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 847b274c78fbeefa3818af68099545f2839c854847mtklein // A release here acts in place of all releases we "should" have been doing in ref(). 857b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { 867b274c78fbeefa3818af68099545f2839c854847mtklein // Like unique(), the acquire is only needed on success, to make sure 877b274c78fbeefa3818af68099545f2839c854847mtklein // code in internal_dispose() doesn't happen before the decrement. 887b274c78fbeefa3818af68099545f2839c854847mtklein this->internal_dispose(); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9203087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG 937f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com void validate() const { 94f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 957f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 9603087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif 977f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 98f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 99f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Allow subclasses to call this if they've overridden internal_dispose 101f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * so they can reset fRefCnt before the destructor is called. Should only 102f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * be called right before calling through to inherited internal_dispose() 103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * or before calling the destructor. 104f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 105f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com void internal_dispose_restore_refcnt_to_1() const { 106a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG 107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkASSERT(0 == fRefCnt); 108a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com fRefCnt = 1; 109a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif 110f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 111f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 112f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 113f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 114f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Called when the ref count goes to 0. 115f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 116f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const { 117f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 118385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary delete this; 119a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com } 12015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 121f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // The following friends are those which override internal_dispose() 122f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // and conditionally call SkRefCnt::internal_dispose(). 123a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com friend class SkWeakRefCnt; 124a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable int32_t fRefCnt; 1264d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com 12710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com typedef SkNoncopyable INHERITED; 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE 13110ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt. 13210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase. 13310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE 13410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else 13510ba006631a0c350aa2bcba188a60404869607c8bungeman@google.comclass SK_API SkRefCnt : public SkRefCntBase { }; 13610ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#endif 13710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com 1387f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1397f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1407f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1417f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com null in on each side of the assignment, and ensuring that ref() is called 1427f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com before unref(), in case the two pointers point to the same object. 1437f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1447f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src) \ 1457f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com do { \ 1467f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (src) src->ref(); \ 1477f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (dst) dst->unref(); \ 1487f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com dst = src; \ 1497f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } while (0) 1507f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1517f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 15277a53de20d723ca21cc824fd97e68aaa60e022eabungeman/** Call obj->ref() and return obj. The obj must not be nullptr. 1537f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1541fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) { 1551fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com SkASSERT(obj); 1561fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com obj->ref(); 1571fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1581fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com} 1591fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com 1601fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj. 1611fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */ 1621fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) { 1637f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->ref(); 1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1661fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref() 1707f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) { 1727f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1737f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->unref(); 1747f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1757f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1767f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 177a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) { 17849f085dddff10473b6ebf832a974288300224e60bsalomon if (obj) { 179a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj->unref(); 18077a53de20d723ca21cc824fd97e68aaa60e022eabungeman obj = nullptr; 181a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org } 182a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org} 183a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org 1847f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1857f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 18677a53de20d723ca21cc824fd97e68aaa60e022eabungemantemplate <typename T> struct SkTUnref { 18777a53de20d723ca21cc824fd97e68aaa60e022eabungeman void operator()(T* t) { t->unref(); } 18877a53de20d723ca21cc824fd97e68aaa60e022eabungeman}; 18977a53de20d723ca21cc824fd97e68aaa60e022eabungeman 190a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/** 19191208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com * Utility class that simply unref's its argument in the destructor. 192a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 1935f939ab658a228dce34a3b14a545638407150b92mtkleintemplate <typename T> class SkAutoTUnref : public std::unique_ptr<T, SkTUnref<T>> { 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1955f939ab658a228dce34a3b14a545638407150b92mtklein explicit SkAutoTUnref(T* obj = nullptr) : std::unique_ptr<T, SkTUnref<T>>(obj) {} 1961dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com 1971138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein T* detach() { return this->release(); } 1981138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein operator T*() const { return this->get(); } 1995f939ab658a228dce34a3b14a545638407150b92mtklein 2005f939ab658a228dce34a3b14a545638407150b92mtklein // Android's std::unique_ptr's operator bool() is sometimes not explicit... 2015f939ab658a228dce34a3b14a545638407150b92mtklein // so override it with our own explcitly explicit version. 2025f939ab658a228dce34a3b14a545638407150b92mtklein explicit operator bool() const { return this->get() != nullptr; } 203a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com}; 204e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( 205a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 206a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 207a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic: 208a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 210e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21208d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16. 21308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// There's only benefit to using this if the deriving class does not otherwise need a vtable. 21408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleintemplate <typename Derived> 21508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinclass SkNVRefCnt : SkNoncopyable { 21608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinpublic: 21708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein SkNVRefCnt() : fRefCnt(1) {} 2183c850c561fcad1ac35bff4ec2875a40ef2309148reed ~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); } 21908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 22008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same: 22108d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unique() needs acquire when it returns true, and no barrier if it returns false; 22208d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - ref() doesn't need any barrier; 22308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unref() needs a release barrier, and an acquire if it's going to call delete. 22408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 2257b274c78fbeefa3818af68099545f2839c854847mtklein bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); } 2267b274c78fbeefa3818af68099545f2839c854847mtklein void ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); } 22790d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed void unref() const { 2287b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { 229385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's assert 23097466ab03e025b6edd94c4f0f369cd0b0d8c3319mtklein delete (const Derived*)this; 23190d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 23290d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 2337b274c78fbeefa3818af68099545f2839c854847mtklein void deref() const { this->unref(); } 234844aa334a43a95cd83a27d565db1d3370d8dc10cFlorin Malita 23508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinprivate: 23608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein mutable int32_t fRefCnt; 23708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein}; 23808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 239bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/////////////////////////////////////////////////////////////////////////////////////////////////// 240bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 241bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/** 242bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shared pointer class to wrap classes that support a ref()/unref() interface. 243bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * 244bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * This can be used for classes inheriting from SkRefCnt, but it also works for other 245bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * classes that match the interface, but have different internal choices: e.g. the hosted class 246bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp. 247bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 248bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedtemplate <typename T> class sk_sp { 249beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman /** Supports safe bool idiom. Obsolete with explicit operator bool. */ 250beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman using unspecified_bool_type = T* sk_sp::*; 251bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic: 252c901c11549acd19e7fc225276f78374ac1600496bungeman using element_type = T; 253c901c11549acd19e7fc225276f78374ac1600496bungeman 254bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp() : fPtr(nullptr) {} 255bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(std::nullptr_t) : fPtr(nullptr) {} 256bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 257bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 258bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shares the underlying object by calling ref(), so that both the argument and the newly 259bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * created sk_sp both have a reference to it. 260bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 261bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} 262c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 263cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {} 264bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 265bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 266bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Move the underlying object from the argument to the newly created sk_sp. Afterwards only 267bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * the new sk_sp will have a reference to the object, and the argument will point to null. 268bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() or unref() will be made. 269bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 270bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} 271c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 272cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {} 273bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 274bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 275bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Adopt the bare pointer into the newly created sk_sp. 276bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() or unref() will be made. 277bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 278bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed explicit sk_sp(T* obj) : fPtr(obj) {} 279bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 280bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 281bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Calls unref() on the underlying object pointer. 282bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 283bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed ~sk_sp() { 284bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed SkSafeUnref(fPtr); 285c901c11549acd19e7fc225276f78374ac1600496bungeman SkDEBUGCODE(fPtr = nullptr); 286bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 287bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 288cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; } 289bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 290bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 291bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shares the underlying object referenced by the argument by calling ref() on it. If this 292bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that 293bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * object. 294bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 295bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(const sk_sp<T>& that) { 296bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed this->reset(SkSafeRef(that.get())); 297bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return *this; 298bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 299c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 300cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp<T>& operator=(const sk_sp<U>& that) { 301cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary this->reset(SkSafeRef(that.get())); 302cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary return *this; 303cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary } 304bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 305bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 306bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held 307bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * a reference to another object, unref() will be called on that object. No call to ref() 308bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * will be made. 309bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 310bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(sk_sp<T>&& that) { 311bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed this->reset(that.release()); 312bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return *this; 313bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 314c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 315cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp<T>& operator=(sk_sp<U>&& that) { 316cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary this->reset(that.release()); 317cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary return *this; 318cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary } 319bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 320beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman T& operator*() const { 321beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman SkASSERT(this->get() != nullptr); 322beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman return *this->get(); 323beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman } 324beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman 32589bd99bed85083c736390f3e340fd30be350d461halcanary // MSVC 2013 does not work correctly with explicit operator bool. 32689bd99bed85083c736390f3e340fd30be350d461halcanary // https://chromium-cpp.appspot.com/#core-blacklist 327beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman // When explicit operator bool can be used, remove operator! and operator unspecified_bool_type. 32889bd99bed85083c736390f3e340fd30be350d461halcanary //explicit operator bool() const { return this->get() != nullptr; } 329beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; } 33089bd99bed85083c736390f3e340fd30be350d461halcanary bool operator!() const { return this->get() == nullptr; } 331bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 332bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* get() const { return fPtr; } 333bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* operator->() const { return fPtr; } 334bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 335bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 336bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Adopt the new bare pointer, and call unref() on any previously held object (if not null). 337bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() will be made. 338bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 339bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed void reset(T* ptr = nullptr) { 340c901c11549acd19e7fc225276f78374ac1600496bungeman // Calling fPtr->unref() may call this->~() or this->reset(T*). 341c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue998 342c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue2262 343c901c11549acd19e7fc225276f78374ac1600496bungeman T* oldPtr = fPtr; 344941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed fPtr = ptr; 345c901c11549acd19e7fc225276f78374ac1600496bungeman SkSafeUnref(oldPtr); 346bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 347bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 348bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 349bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Return the bare pointer, and set the internal object pointer to nullptr. 350bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * The caller must assume ownership of the object, and manage its reference count directly. 351bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to unref() will be made. 352bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 353bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* SK_WARN_UNUSED_RESULT release() { 354bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* ptr = fPtr; 355bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed fPtr = nullptr; 356bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return ptr; 357bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 358bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 359c901c11549acd19e7fc225276f78374ac1600496bungeman void swap(sk_sp<T>& that) /*noexcept*/ { 360c901c11549acd19e7fc225276f78374ac1600496bungeman using std::swap; 361c901c11549acd19e7fc225276f78374ac1600496bungeman swap(fPtr, that.fPtr); 362c901c11549acd19e7fc225276f78374ac1600496bungeman } 363c901c11549acd19e7fc225276f78374ac1600496bungeman 364bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedprivate: 365bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* fPtr; 366bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed}; 367bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 368c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ { 369c901c11549acd19e7fc225276f78374ac1600496bungeman a.swap(b); 370c901c11549acd19e7fc225276f78374ac1600496bungeman} 371c901c11549acd19e7fc225276f78374ac1600496bungeman 372c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) { 373c901c11549acd19e7fc225276f78374ac1600496bungeman return a.get() == b.get(); 374c901c11549acd19e7fc225276f78374ac1600496bungeman} 375c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { 376c901c11549acd19e7fc225276f78374ac1600496bungeman return !a; 377c901c11549acd19e7fc225276f78374ac1600496bungeman} 378c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { 379c901c11549acd19e7fc225276f78374ac1600496bungeman return !b; 380c901c11549acd19e7fc225276f78374ac1600496bungeman} 381c901c11549acd19e7fc225276f78374ac1600496bungeman 382c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) { 383c901c11549acd19e7fc225276f78374ac1600496bungeman return a.get() != b.get(); 384c901c11549acd19e7fc225276f78374ac1600496bungeman} 385c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { 386c901c11549acd19e7fc225276f78374ac1600496bungeman return static_cast<bool>(a); 387c901c11549acd19e7fc225276f78374ac1600496bungeman} 388c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { 389c901c11549acd19e7fc225276f78374ac1600496bungeman return static_cast<bool>(b); 390c901c11549acd19e7fc225276f78374ac1600496bungeman} 391c901c11549acd19e7fc225276f78374ac1600496bungeman 392c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) { 393c901c11549acd19e7fc225276f78374ac1600496bungeman // Provide defined total order on sk_sp. 394c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue1297 395c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue1401 . 396c901c11549acd19e7fc225276f78374ac1600496bungeman return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get()); 397c901c11549acd19e7fc225276f78374ac1600496bungeman} 398c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) { 399c901c11549acd19e7fc225276f78374ac1600496bungeman return std::less<T*>()(a.get(), nullptr); 400c901c11549acd19e7fc225276f78374ac1600496bungeman} 401c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) { 402c901c11549acd19e7fc225276f78374ac1600496bungeman return std::less<T*>()(nullptr, b.get()); 403c901c11549acd19e7fc225276f78374ac1600496bungeman} 404c901c11549acd19e7fc225276f78374ac1600496bungeman 405c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, const sk_sp<U>& b) { 406c901c11549acd19e7fc225276f78374ac1600496bungeman return !(b < a); 407c901c11549acd19e7fc225276f78374ac1600496bungeman} 408c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) { 409c901c11549acd19e7fc225276f78374ac1600496bungeman return !(nullptr < a); 410c901c11549acd19e7fc225276f78374ac1600496bungeman} 411c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) { 412c901c11549acd19e7fc225276f78374ac1600496bungeman return !(b < nullptr); 413c901c11549acd19e7fc225276f78374ac1600496bungeman} 414c901c11549acd19e7fc225276f78374ac1600496bungeman 415c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) { 416c901c11549acd19e7fc225276f78374ac1600496bungeman return b < a; 417c901c11549acd19e7fc225276f78374ac1600496bungeman} 418c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) { 419c901c11549acd19e7fc225276f78374ac1600496bungeman return nullptr < a; 420c901c11549acd19e7fc225276f78374ac1600496bungeman} 421c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) { 422c901c11549acd19e7fc225276f78374ac1600496bungeman return b < nullptr; 423c901c11549acd19e7fc225276f78374ac1600496bungeman} 424c901c11549acd19e7fc225276f78374ac1600496bungeman 425c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, const sk_sp<U>& b) { 426c901c11549acd19e7fc225276f78374ac1600496bungeman return !(a < b); 427c901c11549acd19e7fc225276f78374ac1600496bungeman} 428c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) { 429c901c11549acd19e7fc225276f78374ac1600496bungeman return !(a < nullptr); 430c901c11549acd19e7fc225276f78374ac1600496bungeman} 431c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) { 432c901c11549acd19e7fc225276f78374ac1600496bungeman return !(nullptr < b); 433c901c11549acd19e7fc225276f78374ac1600496bungeman} 434c901c11549acd19e7fc225276f78374ac1600496bungeman 435217c0b3f137d824413e806759bc25378abbe8c18halcanarytemplate <typename T, typename... Args> 436217c0b3f137d824413e806759bc25378abbe8c18halcanarysk_sp<T> sk_make_sp(Args&&... args) { 437217c0b3f137d824413e806759bc25378abbe8c18halcanary return sk_sp<T>(new T(std::forward<Args>(args)...)); 438217c0b3f137d824413e806759bc25378abbe8c18halcanary} 439217c0b3f137d824413e806759bc25378abbe8c18halcanary 440647cc8474828202c98d540f799742e3074a2aacereed#ifdef SK_SUPPORT_TRANSITION_TO_SP_INTERFACES 441647cc8474828202c98d540f799742e3074a2aacereed 442647cc8474828202c98d540f799742e3074a2aacereed/* 443647cc8474828202c98d540f799742e3074a2aacereed * Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null). 444647cc8474828202c98d540f799742e3074a2aacereed * 445647cc8474828202c98d540f799742e3074a2aacereed * This is different than the semantics of the constructor for sk_sp, which just wraps the ptr, 446647cc8474828202c98d540f799742e3074a2aacereed * effectively "adopting" it. 447647cc8474828202c98d540f799742e3074a2aacereed * 448647cc8474828202c98d540f799742e3074a2aacereed * This function may be helpful while we convert callers from ptr-based to sk_sp-based parameters. 449647cc8474828202c98d540f799742e3074a2aacereed */ 450647cc8474828202c98d540f799742e3074a2aacereedtemplate <typename T> sk_sp<T> sk_ref_sp(T* obj) { 451647cc8474828202c98d540f799742e3074a2aacereed return sk_sp<T>(SkSafeRef(obj)); 452647cc8474828202c98d540f799742e3074a2aacereed} 453647cc8474828202c98d540f799742e3074a2aacereed 454647cc8474828202c98d540f799742e3074a2aacereed#endif 455647cc8474828202c98d540f799742e3074a2aacereed 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 457