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