1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2006 The Android Open Source Project
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef SkRefCnt_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkRefCnt_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "../private/SkTLogic.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <atomic>
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <functional>
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <memory>
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <type_traits>
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include <utility>
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** \class SkRefCntBase
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRefCntBase is the base class for objects that may be shared by multiple
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    objects. When an existing owner wants to share a reference, it calls ref().
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    When an owner wants to release its reference, it calls unref(). When the
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    shared object's reference count goes to zero as the result of an unref()
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    call, its (virtual) destructor is called. It is an error for the
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    destructor to be called explicitly (or via the object going out of scope on
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    the stack or calling delete) if getRefCnt() > 1.
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SK_API SkRefCntBase : SkNoncopyable {
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Default construct, initializing the reference count to 1.
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    */
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkRefCntBase() : fRefCnt(1) {}
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Destruct, asserting that the reference count is 1.
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    */
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual ~SkRefCntBase() {
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERTF(getRefCnt() == 1, "fRefCnt was %d", getRefCnt());
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // illegal value, to catch us if we reuse after delete
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRefCnt.store(0, std::memory_order_relaxed);
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Return the reference count. Use only for debugging. */
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int32_t getRefCnt() const {
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRefCnt.load(std::memory_order_relaxed);
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void validate() const {
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(getRefCnt() > 0);
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** May return true if the caller is the only owner.
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Ensures that all previous owner's actions are complete.
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool unique() const {
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (1 == fRefCnt.load(std::memory_order_acquire)) {
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // The acquire barrier is only really needed if we return true.  It
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // prevents code conditioned on the result of unique() from running
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // until previous owners are all totally done calling unref().
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return false;
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Increment the reference count. Must be balanced by a call to unref().
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    */
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void ref() const {
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(getRefCnt() > 0);
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // No barrier required.
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Decrement the reference count. If the reference count is 1 before the
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        decrement, then delete the object. Note that if this is the case, then
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        the object needs to have been allocated via new, and not on the stack.
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    */
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void unref() const {
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(getRefCnt() > 0);
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // A release here acts in place of all releases we "should" have been doing in ref().
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // Like unique(), the acquire is only needed on success, to make sure
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // code in internal_dispose() doesn't happen before the decrement.
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            this->internal_dispose();
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Allow subclasses to call this if they've overridden internal_dispose
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  so they can reset fRefCnt before the destructor is called or if they
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  choose not to call the destructor (e.g. using a free list).
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void internal_dispose_restore_refcnt_to_1() const {
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(0 == getRefCnt());
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fRefCnt.store(1, std::memory_order_relaxed);
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Called when the ref count goes to 0.
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void internal_dispose() const {
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->internal_dispose_restore_refcnt_to_1();
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        delete this;
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // The following friends are those which override internal_dispose()
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // and conditionally call SkRefCnt::internal_dispose().
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    friend class SkWeakRefCnt;
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    mutable std::atomic<int32_t> fRefCnt;
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    typedef SkNoncopyable INHERITED;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_REF_CNT_MIXIN_INCLUDE
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// It is the responsibility of the following include to define the type SkRefCnt.
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This SkRefCnt should normally derive from SkRefCntBase.
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include SK_REF_CNT_MIXIN_INCLUDE
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SK_API SkRefCnt : public SkRefCntBase {
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // "#include SK_REF_CNT_MIXIN_INCLUDE" doesn't work with this build system.
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #if defined(SK_BUILD_FOR_GOOGLE3)
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    public:
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void deref() const { this->unref(); }
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    #endif
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    null in on each side of the assignment, and ensuring that ref() is called
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    before unref(), in case the two pointers point to the same object.
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This version heuristically detects data races, since those otherwise result
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// in redundant reference count decrements, which are exceedingly
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// difficult to debug.
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkRefCnt_SafeAssign(dst, src)   \
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {                                \
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        typedef typename std::remove_reference<decltype(dst)>::type \
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                SkRefCntPtrT;  \
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkRefCntPtrT old_dst = *const_cast<SkRefCntPtrT volatile *>(&dst); \
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (src) src->ref();            \
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (old_dst) old_dst->unref();          \
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (old_dst != *const_cast<SkRefCntPtrT volatile *>(&dst)) { \
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDebugf("Detected racing Skia calls at %s:%d\n", \
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                    __FILE__, __LINE__); \
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } \
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dst = src;                      \
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (0)
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else /* !SK_BUILD_FOR_ANDROID_FRAMEWORK */
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define SkRefCnt_SafeAssign(dst, src)   \
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    do {                                \
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (src) src->ref();            \
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (dst) dst->unref();          \
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        dst = src;                      \
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    } while (0)
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** Call obj->ref() and return obj. The obj must not be nullptr.
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> static inline T* SkRef(T* obj) {
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(obj);
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    obj->ref();
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return obj;
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> static inline T* SkSafeRef(T* obj) {
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (obj) {
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        obj->ref();
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return obj;
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/** Check if the argument is non-null, and if so, call obj->unref()
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> static inline void SkSafeUnref(T* obj) {
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (obj) {
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        obj->unref();
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate<typename T> static inline void SkSafeSetNull(T*& obj) {
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (obj) {
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        obj->unref();
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        obj = nullptr;
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// There's only benefit to using this if the deriving class does not otherwise need a vtable.
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename Derived>
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkNVRefCnt : SkNoncopyable {
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkNVRefCnt() : fRefCnt(1) {}
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), "NVRefCnt was %d", getRefCnt()); }
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    //   - unique() needs acquire when it returns true, and no barrier if it returns false;
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    //   - ref() doesn't need any barrier;
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    //   - unref() needs a release barrier, and an acquire if it's going to call delete.
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void  unref() const {
222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {
223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            // restore the 1 for our destructor's assert
224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed));
225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            delete (const Derived*)this;
226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void  deref() const { this->unref(); }
229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    mutable std::atomic<int32_t> fRefCnt;
232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int32_t getRefCnt() const {
233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return fRefCnt.load(std::memory_order_relaxed);
234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////////////////////////
238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/**
240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  Shared pointer class to wrap classes that support a ref()/unref() interface.
241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  This can be used for classes inheriting from SkRefCnt, but it also works for other
243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  classes that match the interface, but have different internal choices: e.g. the hosted class
244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.
245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> class sk_sp {
247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /** Supports safe bool idiom. Obsolete with explicit operator bool. */
248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    using unspecified_bool_type = T* sk_sp::*;
249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    using element_type = T;
251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    constexpr sk_sp() : fPtr(nullptr) {}
253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    constexpr sk_sp(std::nullptr_t) : fPtr(nullptr) {}
254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Shares the underlying object by calling ref(), so that both the argument and the newly
257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  created sk_sp both have a reference to it.
258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}
260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}
262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Move the underlying object from the argument to the newly created sk_sp. Afterwards only
265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  the new sk_sp will have a reference to the object, and the argument will point to null.
266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  No call to ref() or unref() will be made.
267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}
269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}
271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Adopt the bare pointer into the newly created sk_sp.
274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  No call to ref() or unref() will be made.
275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    explicit sk_sp(T* obj) : fPtr(obj) {}
277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Calls unref() on the underlying object pointer.
280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    ~sk_sp() {
282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkSafeUnref(fPtr);
283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkDEBUGCODE(fPtr = nullptr);
284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }
287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Shares the underlying object referenced by the argument by calling ref() on it. If this
290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that
291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  object.
292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<T>& operator=(const sk_sp<T>& that) {
294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset(SkSafeRef(that.get()));
295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<T>& operator=(const sk_sp<U>& that) {
299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset(SkSafeRef(that.get()));
300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Move the underlying object from the argument to the sk_sp. If the sk_sp previously held
305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  a reference to another object, unref() will be called on that object. No call to ref()
306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  will be made.
307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<T>& operator=(sk_sp<T>&& that) {
309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset(that.release());
310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>
313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sk_sp<T>& operator=(sk_sp<U>&& that) {
314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        this->reset(that.release());
315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this;
316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T& operator*() const {
319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(this->get() != nullptr);
320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return *this->get();
321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // MSVC 2013 does not work correctly with explicit operator bool.
324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // https://chromium-cpp.appspot.com/#core-blacklist
325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // When explicit operator bool can be used, remove operator! and operator unspecified_bool_type.
326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    //explicit operator bool() const { return this->get() != nullptr; }
327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    operator unspecified_bool_type() const { return this->get() ? &sk_sp::fPtr : nullptr; }
328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool operator!() const { return this->get() == nullptr; }
329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* get() const { return fPtr; }
331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* operator->() const { return fPtr; }
332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Adopt the new bare pointer, and call unref() on any previously held object (if not null).
335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  No call to ref() will be made.
336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void reset(T* ptr = nullptr) {
338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Calling fPtr->unref() may call this->~() or this->reset(T*).
339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // http://wg21.cmeerw.net/lwg/issue998
340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // http://wg21.cmeerw.net/lwg/issue2262
341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        T* oldPtr = fPtr;
342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPtr = ptr;
343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkSafeUnref(oldPtr);
344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    /**
347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  Return the bare pointer, and set the internal object pointer to nullptr.
348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  The caller must assume ownership of the object, and manage its reference count directly.
349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     *  No call to unref() will be made.
350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot     */
351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T* SK_WARN_UNUSED_RESULT release() {
352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        T* ptr = fPtr;
353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPtr = nullptr;
354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return ptr;
355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void swap(sk_sp<T>& that) /*noexcept*/ {
358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        using std::swap;
359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        swap(fPtr, that.fPtr);
360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate:
363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    T*  fPtr;
364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {
367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    a.swap(b);
368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) {
371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return a.get() == b.get();
372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !a;
375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !b;
378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) {
381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return a.get() != b.get();
382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {
384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return static_cast<bool>(a);
385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {
387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return static_cast<bool>(b);
388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) {
391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Provide defined total order on sk_sp.
392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // http://wg21.cmeerw.net/lwg/issue1297
393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // http://wg21.cmeerw.net/lwg/issue1401 .
394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get());
395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) {
397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return std::less<T*>()(a.get(), nullptr);
398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) {
400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return std::less<T*>()(nullptr, b.get());
401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, const sk_sp<U>& b) {
404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !(b < a);
405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) {
407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !(nullptr < a);
408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) {
410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !(b < nullptr);
411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) {
414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return b < a;
415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) {
417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return nullptr < a;
418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) {
420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return b < nullptr;
421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, const sk_sp<U>& b) {
424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !(a < b);
425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) {
427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !(a < nullptr);
428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) {
430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return !(nullptr < b);
431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T, typename... Args>
434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotsk_sp<T> sk_make_sp(Args&&... args) {
435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return sk_sp<T>(new T(std::forward<Args>(args)...));
436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null).
440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  This is different than the semantics of the constructor for sk_sp, which just wraps the ptr,
442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *  effectively "adopting" it.
443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> sk_sp<T> sk_ref_sp(T* obj) {
445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return sk_sp<T>(SkSafeRef(obj));
446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
449