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