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>
16801b44c45348144a483793e7b24f4d4092a4f74dbungeman#include <type_traits>
17217c0b3f137d824413e806759bc25378abbe8c18halcanary#include <utility>
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
196d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase
206d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org
2110ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    SkRefCntBase is the base class for objects that may be shared by multiple
22a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    objects. When an existing owner wants to share a reference, it calls ref().
23a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    When an owner wants to release its reference, it calls unref(). When the
24a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    shared object's reference count goes to zero as the result of an unref()
25a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    call, its (virtual) destructor is called. It is an error for the
26a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    destructor to be called explicitly (or via the object going out of scope on
27a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    the stack or calling delete) if getRefCnt() > 1.
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
29e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SK_API SkRefCntBase : SkNoncopyable {
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Default construct, initializing the reference count to 1.
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    SkRefCntBase() : fRefCnt(1) {}
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    /** Destruct, asserting that the reference count is 1.
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    virtual ~SkRefCntBase() {
384c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG
392c4bd0798e929acb9663668985eabe74d7378c46bungeman        SkASSERTF(getRefCnt() == 1, "fRefCnt was %d", getRefCnt());
402c4bd0798e929acb9663668985eabe74d7378c46bungeman        // illegal value, to catch us if we reuse after delete
412c4bd0798e929acb9663668985eabe74d7378c46bungeman        fRefCnt.store(0, std::memory_order_relaxed);
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. */
472c4bd0798e929acb9663668985eabe74d7378c46bungeman    int32_t getRefCnt() const {
482c4bd0798e929acb9663668985eabe74d7378c46bungeman        return fRefCnt.load(std::memory_order_relaxed);
492c4bd0798e929acb9663668985eabe74d7378c46bungeman    }
502c4bd0798e929acb9663668985eabe74d7378c46bungeman
512c4bd0798e929acb9663668985eabe74d7378c46bungeman    void validate() const {
522c4bd0798e929acb9663668985eabe74d7378c46bungeman        SkASSERT(getRefCnt() > 0);
532c4bd0798e929acb9663668985eabe74d7378c46bungeman    }
5421180e26519a23cc69f4673f0b518395fddac57bmtklein#endif
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org    /** May return true if the caller is the only owner.
57f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com     *  Ensures that all previous owner's actions are complete.
58f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com     */
59f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    bool unique() const {
602c4bd0798e929acb9663668985eabe74d7378c46bungeman        if (1 == fRefCnt.load(std::memory_order_acquire)) {
617b274c78fbeefa3818af68099545f2839c854847mtklein            // The acquire barrier is only really needed if we return true.  It
627b274c78fbeefa3818af68099545f2839c854847mtklein            // prevents code conditioned on the result of unique() from running
637b274c78fbeefa3818af68099545f2839c854847mtklein            // until previous owners are all totally done calling unref().
647b274c78fbeefa3818af68099545f2839c854847mtklein            return true;
65f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        }
667b274c78fbeefa3818af68099545f2839c854847mtklein        return false;
67f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    }
68f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Increment the reference count. Must be balanced by a call to unref().
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void ref() const {
722c4bd0798e929acb9663668985eabe74d7378c46bungeman        SkASSERT(getRefCnt() > 0);
732c4bd0798e929acb9663668985eabe74d7378c46bungeman        // No barrier required.
742c4bd0798e929acb9663668985eabe74d7378c46bungeman        (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Decrement the reference count. If the reference count is 1 before the
78a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        decrement, then delete the object. Note that if this is the case, then
79a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        the object needs to have been allocated via new, and not on the stack.
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void unref() const {
822c4bd0798e929acb9663668985eabe74d7378c46bungeman        SkASSERT(getRefCnt() > 0);
837b274c78fbeefa3818af68099545f2839c854847mtklein        // A release here acts in place of all releases we "should" have been doing in ref().
842c4bd0798e929acb9663668985eabe74d7378c46bungeman        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
857b274c78fbeefa3818af68099545f2839c854847mtklein            // Like unique(), the acquire is only needed on success, to make sure
867b274c78fbeefa3818af68099545f2839c854847mtklein            // code in internal_dispose() doesn't happen before the decrement.
877b274c78fbeefa3818af68099545f2839c854847mtklein            this->internal_dispose();
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
91f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected:
92f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    /**
93f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  Allow subclasses to call this if they've overridden internal_dispose
949c5052f16b249d2b7674ea86bd24ed0038ccc61fmtklein     *  so they can reset fRefCnt before the destructor is called or if they
959c5052f16b249d2b7674ea86bd24ed0038ccc61fmtklein     *  choose not to call the destructor (e.g. using a free list).
96f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     */
97f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    void internal_dispose_restore_refcnt_to_1() const {
982c4bd0798e929acb9663668985eabe74d7378c46bungeman        SkASSERT(0 == getRefCnt());
992c4bd0798e929acb9663668985eabe74d7378c46bungeman        fRefCnt.store(1, std::memory_order_relaxed);
100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    }
101f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com
102f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate:
103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    /**
104f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  Called when the ref count goes to 0.
105f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     */
106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    virtual void internal_dispose() const {
107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com        this->internal_dispose_restore_refcnt_to_1();
108385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete this;
109a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    }
11015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
111f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    // The following friends are those which override internal_dispose()
112f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    // and conditionally call SkRefCnt::internal_dispose().
113a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    friend class SkWeakRefCnt;
114a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
1152c4bd0798e929acb9663668985eabe74d7378c46bungeman    mutable std::atomic<int32_t> fRefCnt;
1164d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
11710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    typedef SkNoncopyable INHERITED;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE
12110ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt.
12210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase.
12310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE
12410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else
125f9634b95eccd58acf5b20d98c5d2ee5af353d3d2benjaminwagnerclass SK_API SkRefCnt : public SkRefCntBase {
126f9634b95eccd58acf5b20d98c5d2ee5af353d3d2benjaminwagner    // "#include SK_REF_CNT_MIXIN_INCLUDE" doesn't work with this build system.
1276613cc5186c200e053c5df9bd8f051ffba6e3564Mike Klein    #if defined(SK_BUILD_FOR_GOOGLE3)
128f9634b95eccd58acf5b20d98c5d2ee5af353d3d2benjaminwagner    public:
129f9634b95eccd58acf5b20d98c5d2ee5af353d3d2benjaminwagner        void deref() const { this->unref(); }
130f9634b95eccd58acf5b20d98c5d2ee5af353d3d2benjaminwagner    #endif
131f9634b95eccd58acf5b20d98c5d2ee5af353d3d2benjaminwagner};
13210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#endif
13310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com
1347f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com///////////////////////////////////////////////////////////////////////////////
1357f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1367f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
1377f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    null in on each side of the assignment, and ensuring that ref() is called
1387f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    before unref(), in case the two pointers point to the same object.
1397f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1406dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger
1413849b64cbbdb7db6d5d4af44479b2d7c5bf5e6c7Derek Sollenberger#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
1426dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger// This version heuristically detects data races, since those otherwise result
1436dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger// in redundant reference count decrements, which are exceedingly
1446dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger// difficult to debug.
1456dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger
1466dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger#define SkRefCnt_SafeAssign(dst, src)   \
1476dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger    do {                                \
1486dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        typedef typename std::remove_reference<decltype(dst)>::type \
1496dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger                SkRefCntPtrT;  \
1506dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        SkRefCntPtrT old_dst = *const_cast<SkRefCntPtrT volatile *>(&dst); \
1516dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        if (src) src->ref();            \
1526dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        if (old_dst) old_dst->unref();          \
1536dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        if (old_dst != *const_cast<SkRefCntPtrT volatile *>(&dst)) { \
1546dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger            SkDebugf("Detected racing Skia calls at %s:%d\n", \
1556dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger                    __FILE__, __LINE__); \
1566dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        } \
1576dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger        dst = src;                      \
1586dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger    } while (0)
1596dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger
1603849b64cbbdb7db6d5d4af44479b2d7c5bf5e6c7Derek Sollenberger#else /* !SK_BUILD_FOR_ANDROID_FRAMEWORK */
1616dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger
1627f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src)   \
1637f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    do {                                \
1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        if (src) src->ref();            \
1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        if (dst) dst->unref();          \
1667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        dst = src;                      \
1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    } while (0)
1687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1696dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger#endif
1706dd88144d5ae947090499793d68322f661b6192aDerek Sollenberger
1717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
17277a53de20d723ca21cc824fd97e68aaa60e022eabungeman/** Call obj->ref() and return obj. The obj must not be nullptr.
1737f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1741fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) {
1751fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    SkASSERT(obj);
1761fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    obj->ref();
1771fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    return obj;
1781fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com}
1791fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com
1801fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
1811fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */
1821fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) {
1837f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    if (obj) {
1847f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        obj->ref();
1857f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
1861fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    return obj;
1877f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}
1887f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1897f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref()
1907f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1917f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) {
1927f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    if (obj) {
1937f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        obj->unref();
1947f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
1957f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}
1967f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
197a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) {
19849f085dddff10473b6ebf832a974288300224e60bsalomon    if (obj) {
199a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org        obj->unref();
20077a53de20d723ca21cc824fd97e68aaa60e022eabungeman        obj = nullptr;
201a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    }
202a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org}
203a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org
2047f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com///////////////////////////////////////////////////////////////////////////////
2057f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
20608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.
20708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// There's only benefit to using this if the deriving class does not otherwise need a vtable.
20808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleintemplate <typename Derived>
20908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinclass SkNVRefCnt : SkNoncopyable {
21008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinpublic:
21108d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    SkNVRefCnt() : fRefCnt(1) {}
2122c4bd0798e929acb9663668985eabe74d7378c46bungeman    ~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), "NVRefCnt was %d", getRefCnt()); }
21308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein
21408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
21508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    //   - unique() needs acquire when it returns true, and no barrier if it returns false;
21608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    //   - ref() doesn't need any barrier;
21708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    //   - unref() needs a release barrier, and an acquire if it's going to call delete.
21808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein
2192c4bd0798e929acb9663668985eabe74d7378c46bungeman    bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }
2202c4bd0798e929acb9663668985eabe74d7378c46bungeman    void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
22190d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed    void  unref() const {
2222c4bd0798e929acb9663668985eabe74d7378c46bungeman        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
2232c4bd0798e929acb9663668985eabe74d7378c46bungeman            // restore the 1 for our destructor's assert
2242c4bd0798e929acb9663668985eabe74d7378c46bungeman            SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed));
22597466ab03e025b6edd94c4f0f369cd0b0d8c3319mtklein            delete (const Derived*)this;
22690d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed        }
22790d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed    }
2287b274c78fbeefa3818af68099545f2839c854847mtklein    void  deref() const { this->unref(); }
229844aa334a43a95cd83a27d565db1d3370d8dc10cFlorin Malita
23008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinprivate:
2312c4bd0798e929acb9663668985eabe74d7378c46bungeman    mutable std::atomic<int32_t> fRefCnt;
2322c4bd0798e929acb9663668985eabe74d7378c46bungeman    int32_t getRefCnt() const {
2332c4bd0798e929acb9663668985eabe74d7378c46bungeman        return fRefCnt.load(std::memory_order_relaxed);
2342c4bd0798e929acb9663668985eabe74d7378c46bungeman    }
23508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein};
23608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein
237bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed///////////////////////////////////////////////////////////////////////////////////////////////////
238bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
239bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/**
240bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  Shared pointer class to wrap classes that support a ref()/unref() interface.
241bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *
242bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  This can be used for classes inheriting from SkRefCnt, but it also works for other
243bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  classes that match the interface, but have different internal choices: e.g. the hosted class
244bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
245bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */
246bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedtemplate <typename T> class sk_sp {
247beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    /** Supports safe bool idiom. Obsolete with explicit operator bool. */
248beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    using unspecified_bool_type = T* sk_sp::*;
249bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic:
250c901c11549acd19e7fc225276f78374ac1600496bungeman    using element_type = T;
251c901c11549acd19e7fc225276f78374ac1600496bungeman
25206ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    constexpr sk_sp() : fPtr(nullptr) {}
25306ca8ec87cf6fab57cadd043a5ac18c4154a4129bungeman    constexpr sk_sp(std::nullptr_t) : fPtr(nullptr) {}
254bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
255bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
256bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Shares the underlying object by calling ref(), so that both the argument and the newly
257bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  created sk_sp both have a reference to it.
258bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
259bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
260801b44c45348144a483793e7b24f4d4092a4f74dbungeman    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
261cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
262bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
263bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
264bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Move the underlying object from the argument to the newly created sk_sp. Afterwards only
265bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  the new sk_sp will have a reference to the object, and the argument will point to null.
266bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to ref() or unref() will be made.
267bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
268bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
269801b44c45348144a483793e7b24f4d4092a4f74dbungeman    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
270cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
271bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
272bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
273bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Adopt the bare pointer into the newly created sk_sp.
274bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to ref() or unref() will be made.
275bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
276bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    explicit sk_sp(T* obj) : fPtr(obj) {}
277bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
278bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
279bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Calls unref() on the underlying object pointer.
280bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
281bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    ~sk_sp() {
282bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        SkSafeUnref(fPtr);
283c901c11549acd19e7fc225276f78374ac1600496bungeman        SkDEBUGCODE(fPtr = nullptr);
284bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
285bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
286cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
287bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
288bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
289bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Shares the underlying object referenced by the argument by calling ref() on it. If this
290bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
291bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  object.
292bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
293bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp<T>& operator=(const sk_sp<T>& that) {
294bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        this->reset(SkSafeRef(that.get()));
295bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        return *this;
296bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
297801b44c45348144a483793e7b24f4d4092a4f74dbungeman    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
298cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    sk_sp<T>& operator=(const sk_sp<U>& that) {
299cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        this->reset(SkSafeRef(that.get()));
300cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        return *this;
301cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    }
302bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
303bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
304bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
305bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  a reference to another object, unref() will be called on that object. No call to ref()
306bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  will be made.
307bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
308bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp<T>& operator=(sk_sp<T>&& that) {
309bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        this->reset(that.release());
310bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        return *this;
311bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
312801b44c45348144a483793e7b24f4d4092a4f74dbungeman    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
313cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    sk_sp<T>& operator=(sk_sp<U>&& that) {
314cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        this->reset(that.release());
315cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary        return *this;
316cb6cb3841adec77d178c6d6ed006102077fd3c48halcanary    }
317bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
318beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    T& operator*() const {
319beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        SkASSERT(this->get() != nullptr);
320beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman        return *this->get();
321beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    }
322beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman
32389bd99bed85083c736390f3e340fd30be350d461halcanary    // MSVC 2013 does not work correctly with explicit operator bool.
32489bd99bed85083c736390f3e340fd30be350d461halcanary    // https://chromium-cpp.appspot.com/#core-blacklist
325beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    // When explicit operator bool can be used, remove operator! and operator unspecified_bool_type.
32689bd99bed85083c736390f3e340fd30be350d461halcanary    //explicit operator bool() const { return this->get() != nullptr; }
327beab9e7ba06ea8bd01fcbfd44f2ca2ed69c8a1d9bungeman    operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; }
32889bd99bed85083c736390f3e340fd30be350d461halcanary    bool operator!() const { return this->get() == nullptr; }
329bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
330bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T* get() const { return fPtr; }
331bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T* operator->() const { return fPtr; }
332bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
333bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
334bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Adopt the new bare pointer, and call unref() on any previously held object (if not null).
335bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to ref() will be made.
336bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
337bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    void reset(T* ptr = nullptr) {
338c901c11549acd19e7fc225276f78374ac1600496bungeman        // Calling fPtr->unref() may call this->~() or this->reset(T*).
339c901c11549acd19e7fc225276f78374ac1600496bungeman        // http://wg21.cmeerw.net/lwg/issue998
340c901c11549acd19e7fc225276f78374ac1600496bungeman        // http://wg21.cmeerw.net/lwg/issue2262
341c901c11549acd19e7fc225276f78374ac1600496bungeman        T* oldPtr = fPtr;
342941da9d66171bd8efd2f6c5e25ff90c8c69885c1reed        fPtr = ptr;
343c901c11549acd19e7fc225276f78374ac1600496bungeman        SkSafeUnref(oldPtr);
344bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
345bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
346bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
347bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Return the bare pointer, and set the internal object pointer to nullptr.
348bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  The caller must assume ownership of the object, and manage its reference count directly.
349bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to unref() will be made.
350bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
351bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T* SK_WARN_UNUSED_RESULT release() {
352bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        T* ptr = fPtr;
353bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        fPtr = nullptr;
354bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        return ptr;
355bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
356bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
357c901c11549acd19e7fc225276f78374ac1600496bungeman    void swap(sk_sp<T>& that) /*noexcept*/ {
358c901c11549acd19e7fc225276f78374ac1600496bungeman        using std::swap;
359c901c11549acd19e7fc225276f78374ac1600496bungeman        swap(fPtr, that.fPtr);
360c901c11549acd19e7fc225276f78374ac1600496bungeman    }
361c901c11549acd19e7fc225276f78374ac1600496bungeman
362bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedprivate:
363bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T*  fPtr;
364bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed};
365bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
366c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {
367c901c11549acd19e7fc225276f78374ac1600496bungeman    a.swap(b);
368c901c11549acd19e7fc225276f78374ac1600496bungeman}
369c901c11549acd19e7fc225276f78374ac1600496bungeman
370c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) {
371c901c11549acd19e7fc225276f78374ac1600496bungeman    return a.get() == b.get();
372c901c11549acd19e7fc225276f78374ac1600496bungeman}
373c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
374c901c11549acd19e7fc225276f78374ac1600496bungeman    return !a;
375c901c11549acd19e7fc225276f78374ac1600496bungeman}
376c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
377c901c11549acd19e7fc225276f78374ac1600496bungeman    return !b;
378c901c11549acd19e7fc225276f78374ac1600496bungeman}
379c901c11549acd19e7fc225276f78374ac1600496bungeman
380c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) {
381c901c11549acd19e7fc225276f78374ac1600496bungeman    return a.get() != b.get();
382c901c11549acd19e7fc225276f78374ac1600496bungeman}
383c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
384c901c11549acd19e7fc225276f78374ac1600496bungeman    return static_cast<bool>(a);
385c901c11549acd19e7fc225276f78374ac1600496bungeman}
386c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
387c901c11549acd19e7fc225276f78374ac1600496bungeman    return static_cast<bool>(b);
388c901c11549acd19e7fc225276f78374ac1600496bungeman}
389c901c11549acd19e7fc225276f78374ac1600496bungeman
390c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) {
391c901c11549acd19e7fc225276f78374ac1600496bungeman    // Provide defined total order on sk_sp.
392c901c11549acd19e7fc225276f78374ac1600496bungeman    // http://wg21.cmeerw.net/lwg/issue1297
393c901c11549acd19e7fc225276f78374ac1600496bungeman    // http://wg21.cmeerw.net/lwg/issue1401 .
394c901c11549acd19e7fc225276f78374ac1600496bungeman    return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get());
395c901c11549acd19e7fc225276f78374ac1600496bungeman}
396c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) {
397c901c11549acd19e7fc225276f78374ac1600496bungeman    return std::less<T*>()(a.get(), nullptr);
398c901c11549acd19e7fc225276f78374ac1600496bungeman}
399c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) {
400c901c11549acd19e7fc225276f78374ac1600496bungeman    return std::less<T*>()(nullptr, b.get());
401c901c11549acd19e7fc225276f78374ac1600496bungeman}
402c901c11549acd19e7fc225276f78374ac1600496bungeman
403c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, const sk_sp<U>& b) {
404c901c11549acd19e7fc225276f78374ac1600496bungeman    return !(b < a);
405c901c11549acd19e7fc225276f78374ac1600496bungeman}
406c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) {
407c901c11549acd19e7fc225276f78374ac1600496bungeman    return !(nullptr < a);
408c901c11549acd19e7fc225276f78374ac1600496bungeman}
409c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) {
410c901c11549acd19e7fc225276f78374ac1600496bungeman    return !(b < nullptr);
411c901c11549acd19e7fc225276f78374ac1600496bungeman}
412c901c11549acd19e7fc225276f78374ac1600496bungeman
413c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) {
414c901c11549acd19e7fc225276f78374ac1600496bungeman    return b < a;
415c901c11549acd19e7fc225276f78374ac1600496bungeman}
416c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) {
417c901c11549acd19e7fc225276f78374ac1600496bungeman    return nullptr < a;
418c901c11549acd19e7fc225276f78374ac1600496bungeman}
419c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) {
420c901c11549acd19e7fc225276f78374ac1600496bungeman    return b < nullptr;
421c901c11549acd19e7fc225276f78374ac1600496bungeman}
422c901c11549acd19e7fc225276f78374ac1600496bungeman
423c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, const sk_sp<U>& b) {
424c901c11549acd19e7fc225276f78374ac1600496bungeman    return !(a < b);
425c901c11549acd19e7fc225276f78374ac1600496bungeman}
426c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) {
427c901c11549acd19e7fc225276f78374ac1600496bungeman    return !(a < nullptr);
428c901c11549acd19e7fc225276f78374ac1600496bungeman}
429c901c11549acd19e7fc225276f78374ac1600496bungemantemplate <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) {
430c901c11549acd19e7fc225276f78374ac1600496bungeman    return !(nullptr < b);
431c901c11549acd19e7fc225276f78374ac1600496bungeman}
432c901c11549acd19e7fc225276f78374ac1600496bungeman
433217c0b3f137d824413e806759bc25378abbe8c18halcanarytemplate <typename T, typename... Args>
434217c0b3f137d824413e806759bc25378abbe8c18halcanarysk_sp<T> sk_make_sp(Args&&... args) {
435217c0b3f137d824413e806759bc25378abbe8c18halcanary    return sk_sp<T>(new T(std::forward<Args>(args)...));
436217c0b3f137d824413e806759bc25378abbe8c18halcanary}
437217c0b3f137d824413e806759bc25378abbe8c18halcanary
438647cc8474828202c98d540f799742e3074a2aacereed/*
439647cc8474828202c98d540f799742e3074a2aacereed *  Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null).
440647cc8474828202c98d540f799742e3074a2aacereed *
441647cc8474828202c98d540f799742e3074a2aacereed *  This is different than the semantics of the constructor for sk_sp, which just wraps the ptr,
442647cc8474828202c98d540f799742e3074a2aacereed *  effectively "adopting" it.
443647cc8474828202c98d540f799742e3074a2aacereed */
444647cc8474828202c98d540f799742e3074a2aacereedtemplate <typename T> sk_sp<T> sk_ref_sp(T* obj) {
445647cc8474828202c98d540f799742e3074a2aacereed    return sk_sp<T>(SkSafeRef(obj));
446647cc8474828202c98d540f799742e3074a2aacereed}
447647cc8474828202c98d540f799742e3074a2aacereed
44819d7bd65045e88724ad59a8d7066a9092754c7e4Mike Reedtemplate <typename T> sk_sp<T> sk_ref_sp(const T* obj) {
44919d7bd65045e88724ad59a8d7066a9092754c7e4Mike Reed    return sk_sp<T>(const_cast<T*>(SkSafeRef(obj)));
45019d7bd65045e88724ad59a8d7066a9092754c7e4Mike Reed}
45119d7bd65045e88724ad59a8d7066a9092754c7e4Mike Reed
452647cc8474828202c98d540f799742e3074a2aacereed#endif
453