SkRefCnt.h revision 2c4bd0798e929acb9663668985eabe74d7378c46
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 115f939ab658a228dce34a3b14a545638407150b92mtklein#include "../private/SkTLogic.h" 12f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "SkTypes.h" 132c4bd0798e929acb9663668985eabe74d7378c46bungeman#include <atomic> 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 402c4bd0798e929acb9663668985eabe74d7378c46bungeman SkASSERTF(getRefCnt() == 1, "fRefCnt was %d", getRefCnt()); 412c4bd0798e929acb9663668985eabe74d7378c46bungeman // illegal value, to catch us if we reuse after delete 422c4bd0798e929acb9663668985eabe74d7378c46bungeman fRefCnt.store(0, std::memory_order_relaxed); 434c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif 444c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com } 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4621180e26519a23cc69f4673f0b518395fddac57bmtklein#ifdef SK_DEBUG 47f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Return the reference count. Use only for debugging. */ 482c4bd0798e929acb9663668985eabe74d7378c46bungeman int32_t getRefCnt() const { 492c4bd0798e929acb9663668985eabe74d7378c46bungeman return fRefCnt.load(std::memory_order_relaxed); 502c4bd0798e929acb9663668985eabe74d7378c46bungeman } 512c4bd0798e929acb9663668985eabe74d7378c46bungeman 522c4bd0798e929acb9663668985eabe74d7378c46bungeman void validate() const { 532c4bd0798e929acb9663668985eabe74d7378c46bungeman SkASSERT(getRefCnt() > 0); 542c4bd0798e929acb9663668985eabe74d7378c46bungeman } 5521180e26519a23cc69f4673f0b518395fddac57bmtklein#endif 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 57ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org /** May return true if the caller is the only owner. 58f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com * Ensures that all previous owner's actions are complete. 59f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com */ 60f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool unique() const { 612c4bd0798e929acb9663668985eabe74d7378c46bungeman if (1 == fRefCnt.load(std::memory_order_acquire)) { 627b274c78fbeefa3818af68099545f2839c854847mtklein // The acquire barrier is only really needed if we return true. It 637b274c78fbeefa3818af68099545f2839c854847mtklein // prevents code conditioned on the result of unique() from running 647b274c78fbeefa3818af68099545f2839c854847mtklein // until previous owners are all totally done calling unref(). 657b274c78fbeefa3818af68099545f2839c854847mtklein return true; 66f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 677b274c78fbeefa3818af68099545f2839c854847mtklein return false; 68f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 69f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Increment the reference count. Must be balanced by a call to unref(). 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ref() const { 73ab5d5de420503018b385b73e91b24812916c2080djsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 74ab5d5de420503018b385b73e91b24812916c2080djsollen // Android employs some special subclasses that enable the fRefCnt to 75ab5d5de420503018b385b73e91b24812916c2080djsollen // go to zero, but not below, prior to reusing the object. This breaks 76ab5d5de420503018b385b73e91b24812916c2080djsollen // the use of unique() on such objects and as such should be removed 77ab5d5de420503018b385b73e91b24812916c2080djsollen // once the Android code is fixed. 782c4bd0798e929acb9663668985eabe74d7378c46bungeman SkASSERT(getRefCnt() >= 0); 79ab5d5de420503018b385b73e91b24812916c2080djsollen#else 802c4bd0798e929acb9663668985eabe74d7378c46bungeman SkASSERT(getRefCnt() > 0); 81ab5d5de420503018b385b73e91b24812916c2080djsollen#endif 822c4bd0798e929acb9663668985eabe74d7378c46bungeman // No barrier required. 832c4bd0798e929acb9663668985eabe74d7378c46bungeman (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Decrement the reference count. If the reference count is 1 before the 87a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com decrement, then delete the object. Note that if this is the case, then 88a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the object needs to have been allocated via new, and not on the stack. 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void unref() const { 912c4bd0798e929acb9663668985eabe74d7378c46bungeman SkASSERT(getRefCnt() > 0); 927b274c78fbeefa3818af68099545f2839c854847mtklein // A release here acts in place of all releases we "should" have been doing in ref(). 932c4bd0798e929acb9663668985eabe74d7378c46bungeman if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) { 947b274c78fbeefa3818af68099545f2839c854847mtklein // Like unique(), the acquire is only needed on success, to make sure 957b274c78fbeefa3818af68099545f2839c854847mtklein // code in internal_dispose() doesn't happen before the decrement. 967b274c78fbeefa3818af68099545f2839c854847mtklein this->internal_dispose(); 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 101f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 102f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Allow subclasses to call this if they've overridden internal_dispose 103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * so they can reset fRefCnt before the destructor is called. Should only 104f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * be called right before calling through to inherited internal_dispose() 105f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * or before calling the destructor. 106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com void internal_dispose_restore_refcnt_to_1() const { 108a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG 1092c4bd0798e929acb9663668985eabe74d7378c46bungeman SkASSERT(0 == getRefCnt()); 1102c4bd0798e929acb9663668985eabe74d7378c46bungeman fRefCnt.store(1, std::memory_order_relaxed); 111a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif 112f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 113f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 114f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 115f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 116f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Called when the ref count goes to 0. 117f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 118f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const { 119f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 120385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary delete this; 121a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com } 12215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 123f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // The following friends are those which override internal_dispose() 124f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // and conditionally call SkRefCnt::internal_dispose(). 125a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com friend class SkWeakRefCnt; 126a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com 1272c4bd0798e929acb9663668985eabe74d7378c46bungeman mutable std::atomic<int32_t> fRefCnt; 1284d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com 12910ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com typedef SkNoncopyable INHERITED; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE 13310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt. 13410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase. 13510ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE 13610ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else 13710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.comclass SK_API SkRefCnt : public SkRefCntBase { }; 13810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#endif 13910ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com 1407f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1417f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1427f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1437f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com null in on each side of the assignment, and ensuring that ref() is called 1447f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com before unref(), in case the two pointers point to the same object. 1457f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1467f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src) \ 1477f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com do { \ 1487f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (src) src->ref(); \ 1497f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (dst) dst->unref(); \ 1507f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com dst = src; \ 1517f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } while (0) 1527f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1537f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 15477a53de20d723ca21cc824fd97e68aaa60e022eabungeman/** Call obj->ref() and return obj. The obj must not be nullptr. 1557f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1561fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) { 1571fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com SkASSERT(obj); 1581fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com obj->ref(); 1591fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1601fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com} 1611fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com 1621fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj. 1631fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */ 1641fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) { 1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->ref(); 1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1681fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1707f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref() 1727f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1737f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) { 1747f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1757f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->unref(); 1767f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1777f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1787f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 179a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) { 18049f085dddff10473b6ebf832a974288300224e60bsalomon if (obj) { 181a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj->unref(); 18277a53de20d723ca21cc824fd97e68aaa60e022eabungeman obj = nullptr; 183a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org } 184a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org} 185a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org 1867f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1877f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 18877a53de20d723ca21cc824fd97e68aaa60e022eabungemantemplate <typename T> struct SkTUnref { 18977a53de20d723ca21cc824fd97e68aaa60e022eabungeman void operator()(T* t) { t->unref(); } 19077a53de20d723ca21cc824fd97e68aaa60e022eabungeman}; 19177a53de20d723ca21cc824fd97e68aaa60e022eabungeman 192a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/** 19391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com * Utility class that simply unref's its argument in the destructor. 194a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 1955f939ab658a228dce34a3b14a545638407150b92mtkleintemplate <typename T> class SkAutoTUnref : public std::unique_ptr<T, SkTUnref<T>> { 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1975f939ab658a228dce34a3b14a545638407150b92mtklein explicit SkAutoTUnref(T* obj = nullptr) : std::unique_ptr<T, SkTUnref<T>>(obj) {} 1981dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com 1991138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein operator T*() const { return this->get(); } 2005f939ab658a228dce34a3b14a545638407150b92mtklein 201bbd60689bb080fd147565dbc171f19a6ef177997mtklein#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) 202bbd60689bb080fd147565dbc171f19a6ef177997mtklein // Need to update graphics/Shader.cpp. 203bbd60689bb080fd147565dbc171f19a6ef177997mtklein T* detach() { return this->release(); } 204bbd60689bb080fd147565dbc171f19a6ef177997mtklein#endif 205a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com}; 206e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( 207a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 208a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 209a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic: 210a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 212e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16. 21508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// There's only benefit to using this if the deriving class does not otherwise need a vtable. 21608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleintemplate <typename Derived> 21708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinclass SkNVRefCnt : SkNoncopyable { 21808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinpublic: 21908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein SkNVRefCnt() : fRefCnt(1) {} 2202c4bd0798e929acb9663668985eabe74d7378c46bungeman ~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), "NVRefCnt was %d", getRefCnt()); } 22108d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 22208d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same: 22308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unique() needs acquire when it returns true, and no barrier if it returns false; 22408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - ref() doesn't need any barrier; 22508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unref() needs a release barrier, and an acquire if it's going to call delete. 22608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 2272c4bd0798e929acb9663668985eabe74d7378c46bungeman bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); } 2282c4bd0798e929acb9663668985eabe74d7378c46bungeman void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); } 22990d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed void unref() const { 2302c4bd0798e929acb9663668985eabe74d7378c46bungeman if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) { 2312c4bd0798e929acb9663668985eabe74d7378c46bungeman // restore the 1 for our destructor's assert 2322c4bd0798e929acb9663668985eabe74d7378c46bungeman SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed)); 23397466ab03e025b6edd94c4f0f369cd0b0d8c3319mtklein delete (const Derived*)this; 23490d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 23590d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 2367b274c78fbeefa3818af68099545f2839c854847mtklein void deref() const { this->unref(); } 237844aa334a43a95cd83a27d565db1d3370d8dc10cFlorin Malita 23808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinprivate: 2392c4bd0798e929acb9663668985eabe74d7378c46bungeman mutable std::atomic<int32_t> fRefCnt; 2402c4bd0798e929acb9663668985eabe74d7378c46bungeman int32_t getRefCnt() const { 2412c4bd0798e929acb9663668985eabe74d7378c46bungeman return fRefCnt.load(std::memory_order_relaxed); 2422c4bd0798e929acb9663668985eabe74d7378c46bungeman } 24308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein}; 24408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 245bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/////////////////////////////////////////////////////////////////////////////////////////////////// 246bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 247bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/** 248bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shared pointer class to wrap classes that support a ref()/unref() interface. 249bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * 250bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * This can be used for classes inheriting from SkRefCnt, but it also works for other 251bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * classes that match the interface, but have different internal choices: e.g. the hosted class 252bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp. 253bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 254bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedtemplate <typename T> class sk_sp { 255beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman /** Supports safe bool idiom. Obsolete with explicit operator bool. */ 256beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman using unspecified_bool_type = T* sk_sp::*; 257bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic: 258c901c11549acd19e7fc225276f78374ac1600496bungeman using element_type = T; 259c901c11549acd19e7fc225276f78374ac1600496bungeman 260bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp() : fPtr(nullptr) {} 261bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(std::nullptr_t) : fPtr(nullptr) {} 262bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 263bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 264bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shares the underlying object by calling ref(), so that both the argument and the newly 265bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * created sk_sp both have a reference to it. 266bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 267bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {} 268c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 269cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {} 270bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 271bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 272bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Move the underlying object from the argument to the newly created sk_sp. Afterwards only 273bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * the new sk_sp will have a reference to the object, and the argument will point to null. 274bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() or unref() will be made. 275bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 276bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {} 277c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 278cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {} 279bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 280bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 281bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Adopt the bare pointer into the newly created sk_sp. 282bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() or unref() will be made. 283bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 284bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed explicit sk_sp(T* obj) : fPtr(obj) {} 285bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 286bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 287bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Calls unref() on the underlying object pointer. 288bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 289bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed ~sk_sp() { 290bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed SkSafeUnref(fPtr); 291c901c11549acd19e7fc225276f78374ac1600496bungeman SkDEBUGCODE(fPtr = nullptr); 292bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 293bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 294cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; } 295bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 296bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 297bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Shares the underlying object referenced by the argument by calling ref() on it. If this 298bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that 299bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * object. 300bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 301bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(const sk_sp<T>& that) { 302bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed this->reset(SkSafeRef(that.get())); 303bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return *this; 304bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 305c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 306cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp<T>& operator=(const sk_sp<U>& that) { 307cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary this->reset(SkSafeRef(that.get())); 308cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary return *this; 309cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary } 310bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 311bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 312bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Move the underlying object from the argument to the sk_sp. If the sk_sp previously held 313bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * a reference to another object, unref() will be called on that object. No call to ref() 314bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * will be made. 315bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 316bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed sk_sp<T>& operator=(sk_sp<T>&& that) { 317bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed this->reset(that.release()); 318bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return *this; 319bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 320c901c11549acd19e7fc225276f78374ac1600496bungeman template <typename U, typename = skstd::enable_if_t<skstd::is_convertible<U*, T*>::value>> 321cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary sk_sp<T>& operator=(sk_sp<U>&& that) { 322cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary this->reset(that.release()); 323cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary return *this; 324cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary } 325bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 326beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman T& operator*() const { 327beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman SkASSERT(this->get() != nullptr); 328beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman return *this->get(); 329beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman } 330beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman 33189bd99bed85083c736390f3e340fd30be350d461halcanary // MSVC 2013 does not work correctly with explicit operator bool. 33289bd99bed85083c736390f3e340fd30be350d461halcanary // https://chromium-cpp.appspot.com/#core-blacklist 333beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman // When explicit operator bool can be used, remove operator! and operator unspecified_bool_type. 33489bd99bed85083c736390f3e340fd30be350d461halcanary //explicit operator bool() const { return this->get() != nullptr; } 335beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; } 33689bd99bed85083c736390f3e340fd30be350d461halcanary bool operator!() const { return this->get() == nullptr; } 337bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 338bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* get() const { return fPtr; } 339bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* operator->() const { return fPtr; } 340bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 341bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 342bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Adopt the new bare pointer, and call unref() on any previously held object (if not null). 343bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to ref() will be made. 344bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 345bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed void reset(T* ptr = nullptr) { 346c901c11549acd19e7fc225276f78374ac1600496bungeman // Calling fPtr->unref() may call this->~() or this->reset(T*). 347c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue998 348c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue2262 349c901c11549acd19e7fc225276f78374ac1600496bungeman T* oldPtr = fPtr; 350941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed fPtr = ptr; 351c901c11549acd19e7fc225276f78374ac1600496bungeman SkSafeUnref(oldPtr); 352bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 353bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 354bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed /** 355bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * Return the bare pointer, and set the internal object pointer to nullptr. 356bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * The caller must assume ownership of the object, and manage its reference count directly. 357bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed * No call to unref() will be made. 358bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */ 359bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* SK_WARN_UNUSED_RESULT release() { 360bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* ptr = fPtr; 361bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed fPtr = nullptr; 362bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed return ptr; 363bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed } 364bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 365c901c11549acd19e7fc225276f78374ac1600496bungeman void swap(sk_sp<T>& that) /*noexcept*/ { 366c901c11549acd19e7fc225276f78374ac1600496bungeman using std::swap; 367c901c11549acd19e7fc225276f78374ac1600496bungeman swap(fPtr, that.fPtr); 368c901c11549acd19e7fc225276f78374ac1600496bungeman } 369c901c11549acd19e7fc225276f78374ac1600496bungeman 370bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedprivate: 371bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed T* fPtr; 372bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed}; 373bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed 374c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ { 375c901c11549acd19e7fc225276f78374ac1600496bungeman a.swap(b); 376c901c11549acd19e7fc225276f78374ac1600496bungeman} 377c901c11549acd19e7fc225276f78374ac1600496bungeman 378c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) { 379c901c11549acd19e7fc225276f78374ac1600496bungeman return a.get() == b.get(); 380c901c11549acd19e7fc225276f78374ac1600496bungeman} 381c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { 382c901c11549acd19e7fc225276f78374ac1600496bungeman return !a; 383c901c11549acd19e7fc225276f78374ac1600496bungeman} 384c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { 385c901c11549acd19e7fc225276f78374ac1600496bungeman return !b; 386c901c11549acd19e7fc225276f78374ac1600496bungeman} 387c901c11549acd19e7fc225276f78374ac1600496bungeman 388c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) { 389c901c11549acd19e7fc225276f78374ac1600496bungeman return a.get() != b.get(); 390c901c11549acd19e7fc225276f78374ac1600496bungeman} 391c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ { 392c901c11549acd19e7fc225276f78374ac1600496bungeman return static_cast<bool>(a); 393c901c11549acd19e7fc225276f78374ac1600496bungeman} 394c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ { 395c901c11549acd19e7fc225276f78374ac1600496bungeman return static_cast<bool>(b); 396c901c11549acd19e7fc225276f78374ac1600496bungeman} 397c901c11549acd19e7fc225276f78374ac1600496bungeman 398c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) { 399c901c11549acd19e7fc225276f78374ac1600496bungeman // Provide defined total order on sk_sp. 400c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue1297 401c901c11549acd19e7fc225276f78374ac1600496bungeman // http://wg21.cmeerw.net/lwg/issue1401 . 402c901c11549acd19e7fc225276f78374ac1600496bungeman return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get()); 403c901c11549acd19e7fc225276f78374ac1600496bungeman} 404c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) { 405c901c11549acd19e7fc225276f78374ac1600496bungeman return std::less<T*>()(a.get(), nullptr); 406c901c11549acd19e7fc225276f78374ac1600496bungeman} 407c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) { 408c901c11549acd19e7fc225276f78374ac1600496bungeman return std::less<T*>()(nullptr, b.get()); 409c901c11549acd19e7fc225276f78374ac1600496bungeman} 410c901c11549acd19e7fc225276f78374ac1600496bungeman 411c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, const sk_sp<U>& b) { 412c901c11549acd19e7fc225276f78374ac1600496bungeman return !(b < a); 413c901c11549acd19e7fc225276f78374ac1600496bungeman} 414c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) { 415c901c11549acd19e7fc225276f78374ac1600496bungeman return !(nullptr < a); 416c901c11549acd19e7fc225276f78374ac1600496bungeman} 417c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) { 418c901c11549acd19e7fc225276f78374ac1600496bungeman return !(b < nullptr); 419c901c11549acd19e7fc225276f78374ac1600496bungeman} 420c901c11549acd19e7fc225276f78374ac1600496bungeman 421c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) { 422c901c11549acd19e7fc225276f78374ac1600496bungeman return b < a; 423c901c11549acd19e7fc225276f78374ac1600496bungeman} 424c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) { 425c901c11549acd19e7fc225276f78374ac1600496bungeman return nullptr < a; 426c901c11549acd19e7fc225276f78374ac1600496bungeman} 427c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) { 428c901c11549acd19e7fc225276f78374ac1600496bungeman return b < nullptr; 429c901c11549acd19e7fc225276f78374ac1600496bungeman} 430c901c11549acd19e7fc225276f78374ac1600496bungeman 431c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, const sk_sp<U>& b) { 432c901c11549acd19e7fc225276f78374ac1600496bungeman return !(a < b); 433c901c11549acd19e7fc225276f78374ac1600496bungeman} 434c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) { 435c901c11549acd19e7fc225276f78374ac1600496bungeman return !(a < nullptr); 436c901c11549acd19e7fc225276f78374ac1600496bungeman} 437c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) { 438c901c11549acd19e7fc225276f78374ac1600496bungeman return !(nullptr < b); 439c901c11549acd19e7fc225276f78374ac1600496bungeman} 440c901c11549acd19e7fc225276f78374ac1600496bungeman 441217c0b3f137d824413e806759bc25378abbe8c18halcanarytemplate <typename T, typename... Args> 442217c0b3f137d824413e806759bc25378abbe8c18halcanarysk_sp<T> sk_make_sp(Args&&... args) { 443217c0b3f137d824413e806759bc25378abbe8c18halcanary return sk_sp<T>(new T(std::forward<Args>(args)...)); 444217c0b3f137d824413e806759bc25378abbe8c18halcanary} 445217c0b3f137d824413e806759bc25378abbe8c18halcanary 446647cc8474828202c98d540f799742e3074a2aacereed#ifdef SK_SUPPORT_TRANSITION_TO_SP_INTERFACES 447647cc8474828202c98d540f799742e3074a2aacereed 448647cc8474828202c98d540f799742e3074a2aacereed/* 449647cc8474828202c98d540f799742e3074a2aacereed * Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null). 450647cc8474828202c98d540f799742e3074a2aacereed * 451647cc8474828202c98d540f799742e3074a2aacereed * This is different than the semantics of the constructor for sk_sp, which just wraps the ptr, 452647cc8474828202c98d540f799742e3074a2aacereed * effectively "adopting" it. 453647cc8474828202c98d540f799742e3074a2aacereed * 454647cc8474828202c98d540f799742e3074a2aacereed * This function may be helpful while we convert callers from ptr-based to sk_sp-based parameters. 455647cc8474828202c98d540f799742e3074a2aacereed */ 456647cc8474828202c98d540f799742e3074a2aacereedtemplate <typename T> sk_sp<T> sk_ref_sp(T* obj) { 457647cc8474828202c98d540f799742e3074a2aacereed return sk_sp<T>(SkSafeRef(obj)); 458647cc8474828202c98d540f799742e3074a2aacereed} 459647cc8474828202c98d540f799742e3074a2aacereed 460647cc8474828202c98d540f799742e3074a2aacereed#endif 461647cc8474828202c98d540f799742e3074a2aacereed 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 463