1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkRefCnt_DEFINED 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkRefCnt_DEFINED 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 137b274c78fbeefa3818af68099545f2839c854847mtklein#include "SkAtomics.h" 14977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#include "SkInstCnt.h" 1591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com#include "SkTemplates.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 176d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase 186d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 1910ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase is the base class for objects that may be shared by multiple 20a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com objects. When an existing owner wants to share a reference, it calls ref(). 21a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com When an owner wants to release its reference, it calls unref(). When the 22a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com shared object's reference count goes to zero as the result of an unref() 23a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com call, its (virtual) destructor is called. It is an error for the 24a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com destructor to be called explicitly (or via the object going out of scope on 25a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the stack or calling delete) if getRefCnt() > 1. 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 27e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SK_API SkRefCntBase : SkNoncopyable { 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 296f07665768dc84453316e7b2bbd6049576764cb1mtklein SK_DECLARE_INST_COUNT(SkRefCntBase) 30977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Default construct, initializing the reference count to 1. 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase() : fRefCnt(1) {} 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 35a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com /** Destruct, asserting that the reference count is 1. 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com virtual ~SkRefCntBase() { 384c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG 39b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt); 404c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com fRefCnt = 0; // illegal value, to catch us if we reuse after delete 414c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif 424c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com } 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4421180e26519a23cc69f4673f0b518395fddac57bmtklein#ifdef SK_DEBUG 45f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Return the reference count. Use only for debugging. */ 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t getRefCnt() const { return fRefCnt; } 4721180e26519a23cc69f4673f0b518395fddac57bmtklein#endif 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 49ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org /** May return true if the caller is the only owner. 50f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com * Ensures that all previous owner's actions are complete. 51f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com */ 52f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool unique() const { 537b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire)) { 547b274c78fbeefa3818af68099545f2839c854847mtklein // The acquire barrier is only really needed if we return true. It 557b274c78fbeefa3818af68099545f2839c854847mtklein // prevents code conditioned on the result of unique() from running 567b274c78fbeefa3818af68099545f2839c854847mtklein // until previous owners are all totally done calling unref(). 577b274c78fbeefa3818af68099545f2839c854847mtklein return true; 58f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 597b274c78fbeefa3818af68099545f2839c854847mtklein return false; 60f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 61f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Increment the reference count. Must be balanced by a call to unref(). 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ref() const { 65f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 667b274c78fbeefa3818af68099545f2839c854847mtklein (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); // No barrier required. 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Decrement the reference count. If the reference count is 1 before the 70a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com decrement, then delete the object. Note that if this is the case, then 71a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the object needs to have been allocated via new, and not on the stack. 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void unref() const { 74f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 757b274c78fbeefa3818af68099545f2839c854847mtklein // A release here acts in place of all releases we "should" have been doing in ref(). 767b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { 777b274c78fbeefa3818af68099545f2839c854847mtklein // Like unique(), the acquire is only needed on success, to make sure 787b274c78fbeefa3818af68099545f2839c854847mtklein // code in internal_dispose() doesn't happen before the decrement. 797b274c78fbeefa3818af68099545f2839c854847mtklein this->internal_dispose(); 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG 847f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com void validate() const { 85f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 867f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 8703087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif 887f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 89f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 90f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 91f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Allow subclasses to call this if they've overridden internal_dispose 92f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * so they can reset fRefCnt before the destructor is called. Should only 93f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * be called right before calling through to inherited internal_dispose() 94f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * or before calling the destructor. 95f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 96f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com void internal_dispose_restore_refcnt_to_1() const { 97a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG 98f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkASSERT(0 == fRefCnt); 99a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com fRefCnt = 1; 100a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif 101f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 102f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 104f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 105f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Called when the ref count goes to 0. 106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const { 108f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 109a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com SkDELETE(this); 110a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com } 11115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 112f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // The following friends are those which override internal_dispose() 113f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // and conditionally call SkRefCnt::internal_dispose(). 114a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com friend class SkWeakRefCnt; 115a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable int32_t fRefCnt; 1174d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com 11810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com typedef SkNoncopyable INHERITED; 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12110ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE 12210ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt. 12310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase. 12410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE 12510ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else 12610ba006631a0c350aa2bcba188a60404869607c8bungeman@google.comclass SK_API SkRefCnt : public SkRefCntBase { }; 12710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#endif 12810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com 1297f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1307f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1317f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1327f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com null in on each side of the assignment, and ensuring that ref() is called 1337f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com before unref(), in case the two pointers point to the same object. 1347f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1357f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src) \ 1367f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com do { \ 1377f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (src) src->ref(); \ 1387f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (dst) dst->unref(); \ 1397f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com dst = src; \ 1407f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } while (0) 1417f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1427f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1431fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Call obj->ref() and return obj. The obj must not be NULL. 1447f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1451fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) { 1461fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com SkASSERT(obj); 1471fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com obj->ref(); 1481fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1491fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com} 1501fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com 1511fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj. 1521fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */ 1531fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) { 1547f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1557f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->ref(); 1567f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1571fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1587f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1597f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1607f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref() 1617f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1627f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) { 1637f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->unref(); 1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 168a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) { 16949f085dddff10473b6ebf832a974288300224e60bsalomon if (obj) { 170a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj->unref(); 171a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj = NULL; 172a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org } 173a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org} 174a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org 1757f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1767f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 177a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/** 17891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com * Utility class that simply unref's its argument in the destructor. 179a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 18091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T> class SkAutoTUnref : SkNoncopyable { 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 18291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {} 18391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com ~SkAutoTUnref() { SkSafeUnref(fObj); } 184a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 185a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* get() const { return fObj; } 186a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 1872863f082f2524ebae9e69f382b50065189912b47reed@google.com T* reset(T* obj) { 18868d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com SkSafeUnref(fObj); 18968d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com fObj = obj; 1902863f082f2524ebae9e69f382b50065189912b47reed@google.com return obj; 191a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com } 192a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com 1931dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com void swap(SkAutoTUnref* other) { 1941dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com T* tmp = fObj; 1951dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com fObj = other->fObj; 1961dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com other->fObj = tmp; 1971dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com } 1981dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com 199a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com /** 200a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * Return the hosted object (which may be null), transferring ownership. 201a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * The reference count is not modified, and the internal ptr is set to NULL 202a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * so unref() will not be called in our destructor. A subsequent call to 203a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * detach() will do nothing and return null. 204a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 205a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* detach() { 206a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* obj = fObj; 207a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com fObj = NULL; 208a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com return obj; 209a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com } 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21176f5cc6e9e87ff247c3ef1f4b3fb03668db06e2emtklein T* operator->() const { return fObj; } 212d71b75757335393d9643a5b7a0f2769b6ba52fb6bungeman operator T*() const { return fObj; } 2131448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 21491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comprivate: 21591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com T* fObj; 216a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com}; 217e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( 218a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 219a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 220a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic: 221a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 223e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16. 22608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein// There's only benefit to using this if the deriving class does not otherwise need a vtable. 22708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleintemplate <typename Derived> 22808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinclass SkNVRefCnt : SkNoncopyable { 22908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinpublic: 23008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein SkNVRefCnt() : fRefCnt(1) {} 2313c850c561fcad1ac35bff4ec2875a40ef2309148reed ~SkNVRefCnt() { SkASSERTF(1 == fRefCnt, "NVRefCnt was %d", fRefCnt); } 23208d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 23308d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same: 23408d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unique() needs acquire when it returns true, and no barrier if it returns false; 23508d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - ref() doesn't need any barrier; 23608d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein // - unref() needs a release barrier, and an acquire if it's going to call delete. 23708d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 2387b274c78fbeefa3818af68099545f2839c854847mtklein bool unique() const { return 1 == sk_atomic_load(&fRefCnt, sk_memory_order_acquire); } 2397b274c78fbeefa3818af68099545f2839c854847mtklein void ref() const { (void)sk_atomic_fetch_add(&fRefCnt, +1, sk_memory_order_relaxed); } 24090d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed void unref() const { 2417b274c78fbeefa3818af68099545f2839c854847mtklein if (1 == sk_atomic_fetch_add(&fRefCnt, -1, sk_memory_order_acq_rel)) { 2423c850c561fcad1ac35bff4ec2875a40ef2309148reed SkDEBUGCODE(fRefCnt = 1;) // restore the 1 for our destructor's assert 24390d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed SkDELETE((const Derived*)this); 24490d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 24590d0ff013bbd8e5295d1517d41cb408e9d9f4d93reed } 2467b274c78fbeefa3818af68099545f2839c854847mtklein void deref() const { this->unref(); } 247844aa334a43a95cd83a27d565db1d3370d8dc10cFlorin Malita 24808d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtkleinprivate: 24908d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein mutable int32_t fRefCnt; 25008d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein}; 25108d1fccf6eeec0a9fd5421e59e4d05daccf6e339mtklein 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 253