SkRefCnt.h revision 6d2533ebd2ad5168d08f5a83e681881c0d533949
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 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h" 14977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#include "SkInstCnt.h" 1591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com#include "SkTemplates.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 176d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#ifdef SK_REF_CNT_BASE_INCLUDE 186d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#include SK_REF_CNT_BASE_INCLUDE 196d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#else 206d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase 216d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 226d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org Default implementation of SkRefCntBase. The base class' contract is to 236d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org provide an implementation of aboutToRef. Embedders of skia can specify 246d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org an alternate implementation by setting SK_REF_CNT_BASE_INCLUDE. This is 256d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org useful for adding debug run-time checks to enforce certain usage patterns. 266d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org*/ 276d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.orgclass SK_API SkRefCntBase { 286d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.orgpublic: 296d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org void aboutToRef() const {} 306d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org}; 316d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#endif 326d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkRefCnt 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt is the base class for objects that may be shared by multiple 36a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com objects. When an existing owner wants to share a reference, it calls ref(). 37a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com When an owner wants to release its reference, it calls unref(). When the 38a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com shared object's reference count goes to zero as the result of an unref() 39a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com call, its (virtual) destructor is called. It is an error for the 40a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com destructor to be called explicitly (or via the object going out of scope on 41a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the stack or calling delete) if getRefCnt() > 1. 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 436d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.orgclass SK_API SkRefCnt : public SkRefCntBase { 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com SK_DECLARE_INST_COUNT_ROOT(SkRefCnt) 46977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Default construct, initializing the reference count to 1. 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRefCnt() : fRefCnt(1) {} 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 51a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com /** Destruct, asserting that the reference count is 1. 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 534c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com virtual ~SkRefCnt() { 544c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG 554c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com SkASSERT(fRefCnt == 1); 564c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com fRefCnt = 0; // illegal value, to catch us if we reuse after delete 574c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif 584c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com } 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 60f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Return the reference count. Use only for debugging. */ 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t getRefCnt() const { return fRefCnt; } 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 63f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com /** Returns true if the caller is the only owner. 64f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com * Ensures that all previous owner's actions are complete. 65f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com */ 66f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool unique() const { 67f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com bool const unique = (1 == fRefCnt); 68f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com if (unique) { 69f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // Aquire barrier (L/SL), if not provided by load of fRefCnt. 70f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // Prevents user's 'unique' code from happening before decrements. 71f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com //TODO: issue the barrier. 72f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 73f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com return unique; 74f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com } 75f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Increment the reference count. Must be balanced by a call to unref(). 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ref() const { 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fRefCnt > 0); 806d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org this->INHERITED::aboutToRef(); 81a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com sk_atomic_inc(&fRefCnt); // No barrier required. 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /** Decrement the reference count. If the reference count is 1 before the 85a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com decrement, then delete the object. Note that if this is the case, then 86a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com the object needs to have been allocated via new, and not on the stack. 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void unref() const { 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fRefCnt > 0); 90a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com // Release barrier (SL/S), if not provided below. 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sk_atomic_dec(&fRefCnt) == 1) { 92a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com // Aquire barrier (L/SL), if not provided above. 93a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com // Prevents code in dispose from happening before the decrement. 94a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com sk_membar_aquire__after_atomic_dec(); 95a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com internal_dispose(); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9903087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG 1007f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com void validate() const { 1017f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com SkASSERT(fRefCnt > 0); 1027f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 10303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif 1047f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1059f0af0a285addbeb55db5dd92c3a3b92c144532freed@google.com /** 10639095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org * Alias for unref(), for compatibility with WTF::RefPtr. 10739095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org */ 10839095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org void deref() { this->unref(); } 10939095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org 110f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected: 111f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 112f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Allow subclasses to call this if they've overridden internal_dispose 113f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * so they can reset fRefCnt before the destructor is called. Should only 114f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * be called right before calling through to inherited internal_dispose() 115f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * or before calling the destructor. 116f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 117f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com void internal_dispose_restore_refcnt_to_1() const { 118a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG 119f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com SkASSERT(0 == fRefCnt); 120a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com fRefCnt = 1; 121a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif 122f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com } 123f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com 124f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate: 125f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com /** 1266d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org * Make SkRefCnt non-copyable. 1276d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org */ 1286d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org SkRefCnt(const SkRefCnt&); 1296d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org SkRefCnt& operator=(const SkRefCnt&); 1306d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org 1316d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org /** 132f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com * Called when the ref count goes to 0. 133f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com */ 134f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com virtual void internal_dispose() const { 135f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com this->internal_dispose_restore_refcnt_to_1(); 136a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com SkDELETE(this); 137a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com } 13815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com 139f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // The following friends are those which override internal_dispose() 140f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com // and conditionally call SkRefCnt::internal_dispose(). 141f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com friend class GrTexture; 142a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com friend class SkWeakRefCnt; 143a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable int32_t fRefCnt; 1454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com 1466d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org typedef SkRefCntBase INHERITED; 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1497f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1507f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1517f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1527f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com null in on each side of the assignment, and ensuring that ref() is called 1537f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com before unref(), in case the two pointers point to the same object. 1547f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1557f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src) \ 1567f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com do { \ 1577f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (src) src->ref(); \ 1587f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (dst) dst->unref(); \ 1597f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com dst = src; \ 1607f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } while (0) 1617f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1627f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1631fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Call obj->ref() and return obj. The obj must not be NULL. 1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1651fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) { 1661fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com SkASSERT(obj); 1671fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com obj->ref(); 1681fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1691fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com} 1701fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com 1711fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj. 1721fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */ 1731fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) { 1747f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1757f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->ref(); 1767f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1771fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com return obj; 1787f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1797f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 1807f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref() 1817f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */ 1827f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) { 1837f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com if (obj) { 1847f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com obj->unref(); 1857f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com } 1867f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com} 1877f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 188a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) { 189a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org if (NULL != obj) { 190a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj->unref(); 191a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org obj = NULL; 192a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org } 193a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org} 194a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org 1957f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/////////////////////////////////////////////////////////////////////////////// 1967f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com 197a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/** 19891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com * Utility class that simply unref's its argument in the destructor. 199a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 20091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T> class SkAutoTUnref : SkNoncopyable { 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 20291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {} 20391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com ~SkAutoTUnref() { SkSafeUnref(fObj); } 204a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 205a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* get() const { return fObj; } 206a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 2072863f082f2524ebae9e69f382b50065189912b47reed@google.com T* reset(T* obj) { 20868d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com SkSafeUnref(fObj); 20968d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com fObj = obj; 2102863f082f2524ebae9e69f382b50065189912b47reed@google.com return obj; 211a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com } 212a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com 2131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com void swap(SkAutoTUnref* other) { 2141dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com T* tmp = fObj; 2151dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com fObj = other->fObj; 2161dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com other->fObj = tmp; 2171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com } 2181dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com 219a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com /** 220a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * Return the hosted object (which may be null), transferring ownership. 221a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * The reference count is not modified, and the internal ptr is set to NULL 222a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * so unref() will not be called in our destructor. A subsequent call to 223a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com * detach() will do nothing and return null. 224a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */ 225a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* detach() { 226a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com T* obj = fObj; 227a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com fObj = NULL; 228a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com return obj; 229a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com } 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 231e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com /** 2326f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com * BlockRef<B> is a type which inherits from B, cannot be created, 2336f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com * cannot be deleted, and makes ref and unref private. 234e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com */ 23504640299dc0d71752295a630d58f6160642f3c8ebungeman@google.com template<typename B> class BlockRef : public B { 236e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com private: 237e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com BlockRef(); 2386f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com ~BlockRef(); 239e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com void ref() const; 240e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com void unref() const; 241e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com }; 2421448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 24391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com /** If T is const, the type returned from operator-> will also be const. */ 24491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType; 2451448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 246e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com /** 247e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * SkAutoTUnref assumes ownership of the ref. As a result, it is an error 248e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * for the user to ref or unref through SkAutoTUnref. Therefore 249e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of 250e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com * skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref(). 251e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com */ 25291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com BlockRefType *operator->() const { 25391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com return static_cast<BlockRefType*>(fObj); 254e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com } 25591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com operator T*() { return fObj; } 2561448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com 25791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comprivate: 25891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com T* fObj; 259a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com}; 260a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com 261a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 262a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic: 263a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comclass SkAutoRef : SkNoncopyable { 2677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.compublic: 2687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); } 2697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com ~SkAutoRef() { SkSafeUnref(fObj); } 2707f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comprivate: 2717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com SkRefCnt* fObj; 2727f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}; 273149e2f6159a797989f6f0fa93ecfaa66cdd55c40reed@android.com 2742b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to 2752b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com a SkRefCnt (or subclass) object. 2762b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com */ 2772b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.comtemplate <typename T> class SkRefPtr { 2782b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.compublic: 2792b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefPtr() : fObj(NULL) {} 2802b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); } 2812b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); } 2822b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com ~SkRefPtr() { SkSafeUnref(fObj); } 2832b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com 2842b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefPtr& operator=(const SkRefPtr& rp) { 2852b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefCnt_SafeAssign(fObj, rp.fObj); 2862b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com return *this; 2872b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com } 2882b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefPtr& operator=(T* obj) { 2892b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com SkRefCnt_SafeAssign(fObj, obj); 2902b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com return *this; 2912b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com } 2922b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com 2932b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com T* get() const { return fObj; } 2942b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com T& operator*() const { return *fObj; } 2952b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com T* operator->() const { return fObj; } 2962b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com 2972b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com typedef T* SkRefPtr::*unspecified_bool_type; 2982b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com operator unspecified_bool_type() const { 2992b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com return fObj ? &SkRefPtr::fObj : NULL; 3002b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com } 3012b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com 3022b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.comprivate: 3032b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com T* fObj; 3042b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com}; 3052b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 307