SkRefCnt.h revision 217c0b3f137d824413e806759bc25378abbe8c18
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"
121138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein#include "../private/SkUniquePtr.h"
13f3c15b7cfc4eed2528f7db87ea6c1444b55ee856bungeman#include "SkTypes.h"
14217c0b3f137d824413e806759bc25378abbe8c18halcanary#include <utility>
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
166d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase
176d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org
1810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    SkRefCntBase is the base class for objects that may be shared by multiple
19a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    objects. When an existing owner wants to share a reference, it calls ref().
20a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    When an owner wants to release its reference, it calls unref(). When the
21a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    shared object's reference count goes to zero as the result of an unref()
22a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    call, its (virtual) destructor is called. It is an error for the
23a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    destructor to be called explicitly (or via the object going out of scope on
24a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    the stack or calling delete) if getRefCnt() > 1.
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
26e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SK_API SkRefCntBase : SkNoncopyable {
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Default construct, initializing the reference count to 1.
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    SkRefCntBase() : fRefCnt(1) {}
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    /** Destruct, asserting that the reference count is 1.
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
3410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    virtual ~SkRefCntBase() {
354c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG
36b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein        SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt);
374c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com        fRefCnt = 0;    // illegal value, to catch us if we reuse after delete
384c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif
394c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com    }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4121180e26519a23cc69f4673f0b518395fddac57bmtklein#ifdef SK_DEBUG
42f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    /** Return the reference count. Use only for debugging. */
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t getRefCnt() const { return fRefCnt; }
4421180e26519a23cc69f4673f0b518395fddac57bmtklein#endif
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org    /** May return true if the caller is the only owner.
47f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com     *  Ensures that all previous owner's actions are complete.
48f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com     */
49f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    bool unique() const {
507b274c78fbeefa3818af68099545f2839c854847mtklein        if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) {
517b274c78fbeefa3818af68099545f2839c854847mtklein            // The acquire barrier is only really needed if we return true.  It
527b274c78fbeefa3818af68099545f2839c854847mtklein            // prevents code conditioned on the result of unique() from running
537b274c78fbeefa3818af68099545f2839c854847mtklein            // until previous owners are all totally done calling unref().
547b274c78fbeefa3818af68099545f2839c854847mtklein            return true;
55f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        }
567b274c78fbeefa3818af68099545f2839c854847mtklein        return false;
57f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    }
58f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Increment the reference count. Must be balanced by a call to unref().
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void ref() const {
62ab5d5de420503018b385b73e91b24812916c2080djsollen#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
63ab5d5de420503018b385b73e91b24812916c2080djsollen        // Android employs some special subclasses that enable the fRefCnt to
64ab5d5de420503018b385b73e91b24812916c2080djsollen        // go to zero, but not below, prior to reusing the object.  This breaks
65ab5d5de420503018b385b73e91b24812916c2080djsollen        // the use of unique() on such objects and as such should be removed
66ab5d5de420503018b385b73e91b24812916c2080djsollen        // once the Android code is fixed.
67ab5d5de420503018b385b73e91b24812916c2080djsollen        SkASSERT(fRefCnt >= 0);
68ab5d5de420503018b385b73e91b24812916c2080djsollen#else
69f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org        SkASSERT(fRefCnt > 0);
70ab5d5de420503018b385b73e91b24812916c2080djsollen#endif
717b274c78fbeefa3818af68099545f2839c854847mtklein        (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed);  // No barrier required.
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Decrement the reference count. If the reference count is 1 before the
75a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        decrement, then delete the object. Note that if this is the case, then
76a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        the object needs to have been allocated via new, and not on the stack.
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void unref() const {
79f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org        SkASSERT(fRefCnt > 0);
807b274c78fbeefa3818af68099545f2839c854847mtklein        // A release here acts in place of all releases we "should" have been doing in ref().
817b274c78fbeefa3818af68099545f2839c854847mtklein        if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
827b274c78fbeefa3818af68099545f2839c854847mtklein            // Like unique(), the acquire is only needed on success, to make sure
837b274c78fbeefa3818af68099545f2839c854847mtklein            // code in internal_dispose() doesn't happen before the decrement.
847b274c78fbeefa3818af68099545f2839c854847mtklein            this->internal_dispose();
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8803087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG
897f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    void validate() const {
90f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org        SkASSERT(fRefCnt > 0);
917f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
9203087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif
937f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
94f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected:
95f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    /**
96f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  Allow subclasses to call this if they've overridden internal_dispose
97f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  so they can reset fRefCnt before the destructor is called. Should only
98f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  be called right before calling through to inherited internal_dispose()
99f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  or before calling the destructor.
100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     */
101f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    void internal_dispose_restore_refcnt_to_1() const {
102a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG
103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com        SkASSERT(0 == fRefCnt);
104a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        fRefCnt = 1;
105a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif
106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    }
107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com
108f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate:
109f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    /**
110f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  Called when the ref count goes to 0.
111f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     */
112f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    virtual void internal_dispose() const {
113f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com        this->internal_dispose_restore_refcnt_to_1();
114385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary        delete this;
115a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    }
11615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
117f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    // The following friends are those which override internal_dispose()
118f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    // and conditionally call SkRefCnt::internal_dispose().
119a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    friend class SkWeakRefCnt;
120a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    mutable int32_t fRefCnt;
1224d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
12310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com    typedef SkNoncopyable INHERITED;
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12610ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE
12710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt.
12810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase.
12910ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE
13010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else
13110ba006631a0c350aa2bcba188a60404869607c8bungeman@google.comclass SK_API SkRefCnt : public SkRefCntBase { };
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 */
1407f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src)   \
1417f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    do {                                \
1427f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        if (src) src->ref();            \
1437f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        if (dst) dst->unref();          \
1447f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        dst = src;                      \
1457f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    } while (0)
1467f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1477f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
14877a53de20d723ca21cc824fd97e68aaa60e022eabungeman/** Call obj->ref() and return obj. The obj must not be nullptr.
1497f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1501fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) {
1511fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    SkASSERT(obj);
1521fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    obj->ref();
1531fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    return obj;
1541fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com}
1551fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com
1561fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
1571fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */
1581fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) {
1597f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    if (obj) {
1607f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        obj->ref();
1617f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
1621fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    return obj;
1637f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}
1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref()
1667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) {
1687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    if (obj) {
1697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        obj->unref();
1707f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
1717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}
1727f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
173a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) {
17449f085dddff10473b6ebf832a974288300224e60bsalomon    if (obj) {
175a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org        obj->unref();
17677a53de20d723ca21cc824fd97e68aaa60e022eabungeman        obj = nullptr;
177a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    }
178a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org}
179a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org
1807f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com///////////////////////////////////////////////////////////////////////////////
1817f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
18277a53de20d723ca21cc824fd97e68aaa60e022eabungemantemplate <typename T> struct SkTUnref {
18377a53de20d723ca21cc824fd97e68aaa60e022eabungeman    void operator()(T* t) { t->unref(); }
18477a53de20d723ca21cc824fd97e68aaa60e022eabungeman};
18577a53de20d723ca21cc824fd97e68aaa60e022eabungeman
186a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/**
18791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com *  Utility class that simply unref's its argument in the destructor.
188a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */
1891138be45eac9dd21b094c9774a6f9c612f9f8fa8mtkleintemplate <typename T> class SkAutoTUnref : public skstd::unique_ptr<T, SkTUnref<T>> {
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
1911138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein    explicit SkAutoTUnref(T* obj = nullptr) : skstd::unique_ptr<T, SkTUnref<T>>(obj) {}
1921dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
1931138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein    T* detach() { return this->release(); }
1941138be45eac9dd21b094c9774a6f9c612f9f8fa8mtklein    operator T*() const { return this->get(); }
195a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com};
196e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :(
197a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com
198a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
199a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic:
200a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com    SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {}
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
202e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref)
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.
20508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// There's only benefit to using this if the deriving class does not otherwise need a vtable.
20608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleintemplate <typename Derived>
20708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinclass SkNVRefCnt : SkNoncopyable {
20808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinpublic:
20908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    SkNVRefCnt() : fRefCnt(1) {}
2103c850c561fcad1ac35bff4ec2875a40ef2309148reed    ~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); }
21108d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein
21208d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
21308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    //   - unique() needs acquire when it returns true, and no barrier if it returns false;
21408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    //   - ref() doesn't need any barrier;
21508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    //   - unref() needs a release barrier, and an acquire if it's going to call delete.
21608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein
2177b274c78fbeefa3818af68099545f2839c854847mtklein    bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); }
2187b274c78fbeefa3818af68099545f2839c854847mtklein    void    ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); }
21990d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed    void  unref() const {
2207b274c78fbeefa3818af68099545f2839c854847mtklein        if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) {
221385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary            SkDEBUGCODE(fRefCnt = 1;)  // restore the 1 for our destructor's assert
22297466ab03e025b6edd94c4f0f369cd0b0d8c3319mtklein            delete (const Derived*)this;
22390d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed        }
22490d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed    }
2257b274c78fbeefa3818af68099545f2839c854847mtklein    void  deref() const { this->unref(); }
226844aa334a43a95cd83a27d565db1d3370d8dc10cFlorin Malita
22708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinprivate:
22808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein    mutable int32_t fRefCnt;
22908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein};
23008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein
231bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed///////////////////////////////////////////////////////////////////////////////////////////////////
232bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
233bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed/**
234bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  Shared pointer class to wrap classes that support a ref()/unref() interface.
235bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *
236bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  This can be used for classes inheriting from SkRefCnt, but it also works for other
237bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  classes that match the interface, but have different internal choices: e.g. the hosted class
238bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed *  may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
239bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed */
240bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedtemplate <typename T> class sk_sp {
241bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedpublic:
242bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp() : fPtr(nullptr) {}
243bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp(std::nullptr_t) : fPtr(nullptr) {}
244bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
245bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
246bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Shares the underlying object by calling ref(), so that both the argument and the newly
247bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  created sk_sp both have a reference to it.
248bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
249bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
250bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
251bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
252bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Move the underlying object from the argument to the newly created sk_sp. Afterwards only
253bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  the new sk_sp will have a reference to the object, and the argument will point to null.
254bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to ref() or unref() will be made.
255bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
256bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
257bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
258bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
259bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Adopt the bare pointer into the newly created sk_sp.
260bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to ref() or unref() will be made.
261bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
262bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    explicit sk_sp(T* obj) : fPtr(obj) {}
263bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
264bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
265bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Calls unref() on the underlying object pointer.
266bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
267bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    ~sk_sp() {
268bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        SkSafeUnref(fPtr);
269bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
270bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
271bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp<T>& operator=(std::nullptr_t) { this->reset(); }
272bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
273bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
274bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Shares the underlying object referenced by the argument by calling ref() on it. If this
275bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
276bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  object.
277bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
278bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp<T>& operator=(const sk_sp<T>& that) {
279bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        this->reset(SkSafeRef(that.get()));
280bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        return *this;
281bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
282bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
283bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
284bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
285bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  a reference to another object, unref() will be called on that object. No call to ref()
286bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  will be made.
287bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
288bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    sk_sp<T>& operator=(sk_sp<T>&& that) {
289bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        this->reset(that.release());
290bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        return *this;
291bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
292bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
293bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    bool operator==(std::nullptr_t) const { return this->get() == nullptr; }
294bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    bool operator!=(std::nullptr_t) const { return this->get() != nullptr; }
295bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
296bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    bool operator==(const sk_sp<T>& that) const { return this->get() == that.get(); }
297bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    bool operator!=(const sk_sp<T>& that) const { return this->get() != that.get(); }
298bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
299bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    explicit operator bool() const { return this->get() != nullptr; }
300bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
301bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T* get() const { return fPtr; }
302bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T* operator->() const { return fPtr; }
303bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
304bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
305bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Adopt the new bare pointer, and call unref() on any previously held object (if not null).
306bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to ref() will be made.
307bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
308bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    void reset(T* ptr = nullptr) {
309bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        if (fPtr != ptr) {
310bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed            SkSafeUnref(fPtr);
311bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed            fPtr = ptr;
312bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        }
313bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
314bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
315bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    /**
316bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  Return the bare pointer, and set the internal object pointer to nullptr.
317bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  The caller must assume ownership of the object, and manage its reference count directly.
318bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     *  No call to unref() will be made.
319bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed     */
320bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T* SK_WARN_UNUSED_RESULT release() {
321bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        T* ptr = fPtr;
322bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        fPtr = nullptr;
323bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed        return ptr;
324bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    }
325bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
326bb7b043b2db64197d2f6a1edaf3562a50c77afb1reedprivate:
327bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed    T*  fPtr;
328bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed};
329bb7b043b2db64197d2f6a1edaf3562a50c77afb1reed
330217c0b3f137d824413e806759bc25378abbe8c18halcanarytemplate <typename T, typename... Args>
331217c0b3f137d824413e806759bc25378abbe8c18halcanarysk_sp<T> sk_make_sp(Args&&... args) {
332217c0b3f137d824413e806759bc25378abbe8c18halcanary    return sk_sp<T>(new T(std::forward<Args>(args)...));
333217c0b3f137d824413e806759bc25378abbe8c18halcanary}
334217c0b3f137d824413e806759bc25378abbe8c18halcanary
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
336