SkRefCnt.h revision 49f085dddff10473b6ebf832a974288300224e60
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 13ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org#include "SkDynamicAnnotations.h" 1486b0de4745a8a8317b54f23878498633b9210a8fcommit-bot@chromium.org#include "SkThread.h" 15977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#include "SkInstCnt.h" 1691208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com#include "SkTemplates.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 186d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase 196d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 2010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase is the base class for objects that may be shared by multiple 21a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com objects. When an existing owner wants to share a reference, it calls ref(). 22a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com When an owner wants to release its reference, it calls unref(). When the 23a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com shared object's reference count goes to zero as the result of an unref() 24a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com call, its (virtual) destructor is called. It is an error for the 25a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com destructor to be called explicitly (or via the object going out of scope on 26a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the stack or calling delete) if getRefCnt() > 1. 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 28e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass SK_API SkRefCntBase : SkNoncopyable { 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SK_DECLARE_INST_COUNT_ROOT(SkRefCntBase) 31977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Default construct, initializing the reference count to 1. 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com SkRefCntBase() : fRefCnt(1) {} 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 36a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com /** Destruct, asserting that the reference count is 1. 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 3810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com virtual ~SkRefCntBase() { 394c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG 40b59161f0000eb4aca3dcef29f27ffd0fb5a568e5mtklein SkASSERTF(fRefCnt == 1, "fRefCnt was %d", fRefCnt); 414c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com fRefCnt = 0; // illegal value, to catch us if we reuse after delete 424c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif 434c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com } 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 45f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Return the reference count. Use only for debugging. */ 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t getRefCnt() const { return fRefCnt; } 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 48ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org /** May return true if the caller is the only owner. 49f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com * Ensures that all previous owner's actions are complete. 50f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com */ 51f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool unique() const { 52ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org // We believe we're reading fRefCnt in a safe way here, so we stifle the TSAN warning about 53ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org // an unproctected read. Generally, don't read fRefCnt, and don't stifle this warning. 54ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org bool const unique = (1 == SK_ANNOTATE_UNPROTECTED_READ(fRefCnt)); 55f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com if (unique) { 56d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com // Acquire barrier (L/SL), if not provided by load of fRefCnt. 57f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // Prevents user's 'unique' code from happening before decrements. 58f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com //TODO: issue the barrier. 59f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 60f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com return unique; 61f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 62f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Increment the reference count. Must be balanced by a call to unref(). 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ref() const { 66f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 67a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com sk_atomic_inc(&fRefCnt); // No barrier required. 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Decrement the reference count. If the reference count is 1 before the 71a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com decrement, then delete the object. Note that if this is the case, then 72a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the object needs to have been allocated via new, and not on the stack. 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void unref() const { 75f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 76a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com // Release barrier (SL/S), if not provided below. 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sk_atomic_dec(&fRefCnt) == 1) { 78d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com // Acquire barrier (L/SL), if not provided above. 79a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com // Prevents code in dispose from happening before the decrement. 80d9947f605a335363b0a0541d6d8cb7a7113ed788bungeman@google.com sk_membar_acquire__after_atomic_dec(); 81a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com internal_dispose(); 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8503087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG 867f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com void validate() const { 87f672cead70404080a991ebfb86c38316a4589b23commit-bot@chromium.org SkASSERT(fRefCnt > 0); 887f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 8903087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif 907f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 91f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 92f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 93f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Allow subclasses to call this if they've overridden internal_dispose 94f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * so they can reset fRefCnt before the destructor is called. Should only 95f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * be called right before calling through to inherited internal_dispose() 96f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * or before calling the destructor. 97f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 98f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com void internal_dispose_restore_refcnt_to_1() const { 99a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG 100f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkASSERT(0 == fRefCnt); 101a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com fRefCnt = 1; 102a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif 103f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 104f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 105f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 106f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 107f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Called when the ref count goes to 0. 108f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 109f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const { 110f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 111a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com SkDELETE(this); 112a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com } 11315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 114f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // The following friends are those which override internal_dispose() 115f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // and conditionally call SkRefCnt::internal_dispose(). 116a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com friend class SkWeakRefCnt; 117a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable int32_t fRefCnt; 1194d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com 12010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com typedef SkNoncopyable INHERITED; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12310ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#ifdef SK_REF_CNT_MIXIN_INCLUDE 12410ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// It is the responsibility of the following include to define the type SkRefCnt. 12510ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com// This SkRefCnt should normally derive from SkRefCntBase. 12610ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#include SK_REF_CNT_MIXIN_INCLUDE 12710ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#else 12810ba006631a0c350aa2bcba188a60404869607c8bungeman@google.comclass SK_API SkRefCnt : public SkRefCntBase { }; 12910ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com#endif 13010ba006631a0c350aa2bcba188a60404869607c8bungeman@google.com 1317f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1327f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1337f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1347f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com null in on each side of the assignment, and ensuring that ref() is called 1357f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com before unref(), in case the two pointers point to the same object. 1367f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1377f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src) \ 1387f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com do { \ 1397f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (src) src->ref(); \ 1407f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (dst) dst->unref(); \ 1417f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com dst = src; \ 1427f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } while (0) 1437f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1447f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1451fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Call obj->ref() and return obj. The obj must not be NULL. 1467f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1471fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) { 1481fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com SkASSERT(obj); 1491fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com obj->ref(); 1501fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1511fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com} 1521fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com 1531fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj. 1541fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */ 1551fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) { 1567f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1577f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->ref(); 1587f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1591fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1607f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1617f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1627f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref() 1637f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) { 1657f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->unref(); 1677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 170a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) { 17149f085dddff10473b6ebf832a974288300224e60bsalomon if (obj) { 172a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj->unref(); 173a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj = NULL; 174a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org } 175a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org} 176a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org 1777f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1787f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 179a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/** 18091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com * Utility class that simply unref's its argument in the destructor. 181a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 18291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T> class SkAutoTUnref : SkNoncopyable { 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 18491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {} 18591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com ~SkAutoTUnref() { SkSafeUnref(fObj); } 186a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 187a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* get() const { return fObj; } 188a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 1892863f082f2524ebae9e69f382b50065189912b47reed@google.com T* reset(T* obj) { 19068d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com SkSafeUnref(fObj); 19168d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com fObj = obj; 1922863f082f2524ebae9e69f382b50065189912b47reed@google.com return obj; 193a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com } 194a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com 1951dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com void swap(SkAutoTUnref* other) { 1961dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com T* tmp = fObj; 1971dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com fObj = other->fObj; 1981dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com other->fObj = tmp; 1991dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com } 2001dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com 201a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com /** 202a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * Return the hosted object (which may be null), transferring ownership. 203a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * The reference count is not modified, and the internal ptr is set to NULL 204a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * so unref() will not be called in our destructor. A subsequent call to 205a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * detach() will do nothing and return null. 206a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 207a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* detach() { 208a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* obj = fObj; 209a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com fObj = NULL; 210a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com return obj; 211a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com } 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 213e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com /** 2146f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com * BlockRef<B> is a type which inherits from B, cannot be created, 2156f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com * cannot be deleted, and makes ref and unref private. 216e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com */ 21704640299dc0d71752295a630d58f6160642f3c8ebungeman@google.com template<typename B> class BlockRef : public B { 218e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com private: 219e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com BlockRef(); 2206f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com ~BlockRef(); 221e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com void ref() const; 222e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com void unref() const; 223e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com }; 2241448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 22591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com /** If T is const, the type returned from operator-> will also be const. */ 22691208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType; 2271448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 228e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com /** 229e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * SkAutoTUnref assumes ownership of the ref. As a result, it is an error 230e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * for the user to ref or unref through SkAutoTUnref. Therefore 231e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of 232e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref(). 233e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com */ 23491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com BlockRefType *operator->() const { 23591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com return static_cast<BlockRefType*>(fObj); 236e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com } 23791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com operator T*() { return fObj; } 2381448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 23991208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comprivate: 24091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com T* fObj; 241a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com}; 242e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org// Can't use the #define trick below to guard a bare SkAutoTUnref(...) because it's templated. :( 243a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 244a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 245a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic: 246a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 248e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoUnref(...) SK_REQUIRE_LOCAL_VAR(SkAutoUnref) 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 251