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