11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkRefCnt_DEFINED 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRefCnt_DEFINED 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h" 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** \class SkRefCnt 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt is the base class for objects that may be shared by multiple 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project objects. When a new owner wants a reference, it calls ref(). When an owner 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project wants to release its reference, it calls unref(). When the shared object's 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project reference count goes to zero as the result of an unref() call, its (virtual) 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project destructor is called. It is an error for the destructor to be called 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project explicitly (or via the object going out of scope on the stack or calling 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project delete) if getRefCnt() > 1. 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 25137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenbergerclass SK_API SkRefCnt : SkNoncopyable { 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Default construct, initializing the reference count to 1. 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt() : fRefCnt(1) {} 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Destruct, asserting that the reference count is 1. 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger virtual ~SkRefCnt() { 341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_DEBUG 351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(fRefCnt == 1); 361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fRefCnt = 0; // illegal value, to catch us if we reuse after delete 371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif 381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Return the reference count. 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int32_t getRefCnt() const { return fRefCnt; } 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Increment the reference count. Must be balanced by a call to unref(). 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void ref() const { 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fRefCnt > 0); 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_atomic_inc(&fRefCnt); 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Decrement the reference count. If the reference count is 1 before the 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project decrement, then call delete on the object. Note that if this is the 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case, then the object needs to have been allocated via new, and not on 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project the stack. 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void unref() const { 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fRefCnt > 0); 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (sk_atomic_dec(&fRefCnt) == 1) { 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRefCnt = 1; // so our destructor won't complain 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDELETE(this); 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger void validate() const { 651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(fRefCnt > 0); 661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mutable int32_t fRefCnt; 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger null in on each side of the assignment, and ensuring that ref() is called 761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger before unref(), in case the two pointers point to the same object. 771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define SkRefCnt_SafeAssign(dst, src) \ 791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger do { \ 801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (src) src->ref(); \ 811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (dst) dst->unref(); \ 821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst = src; \ 831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } while (0) 841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/** Check if the argument is non-null, and if so, call obj->ref() 871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertemplate <typename T> static inline void SkSafeRef(T* obj) { 891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (obj) { 901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger obj->ref(); 911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/** Check if the argument is non-null, and if so, call obj->unref() 951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertemplate <typename T> static inline void SkSafeUnref(T* obj) { 971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (obj) { 981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger obj->unref(); 991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 10405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger/** 10505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * Utility class that simply unref's its argument in the destructor. 10605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */ 10705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergertemplate <typename T> class SkAutoTUnref : SkNoncopyable { 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 1091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {} 11005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger ~SkAutoTUnref() { SkSafeUnref(fObj); } 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* get() const { return fObj; } 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger void reset(T* obj) { 1151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkSafeUnref(fObj); 1161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fObj = obj; 1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 11905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger /** 12005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * Return the hosted object (which may be null), transferring ownership. 12105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * The reference count is not modified, and the internal ptr is set to NULL 12205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * so unref() will not be called in our destructor. A subsequent call to 12305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * detach() will do nothing and return null. 12405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */ 12505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* detach() { 12605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* obj = fObj; 12705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger fObj = NULL; 12805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger return obj; 12905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger } 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 13205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* fObj; 13305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}; 13405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger 13505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 13605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerpublic: 13705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerclass SkAutoRef : SkNoncopyable { 1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerpublic: 1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); } 1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ~SkAutoRef() { SkSafeUnref(fObj); } 1441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerprivate: 1451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkRefCnt* fObj; 1461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}; 147dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to 14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger a SkRefCnt (or subclass) object. 15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */ 15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergertemplate <typename T> class SkRefPtr { 15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic: 15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr() : fObj(NULL) {} 15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); } 15540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); } 15640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger ~SkRefPtr() { SkSafeUnref(fObj); } 15740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr& operator=(const SkRefPtr& rp) { 15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefCnt_SafeAssign(fObj, rp.fObj); 16040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return *this; 16140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 16240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr& operator=(T* obj) { 16340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefCnt_SafeAssign(fObj, obj); 16440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return *this; 16540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 16640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* get() const { return fObj; } 16840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T& operator*() const { return *fObj; } 16940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* operator->() const { return fObj; } 17040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger typedef T* SkRefPtr::*unspecified_bool_type; 17205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger operator unspecified_bool_type() const { 17305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger return fObj ? &SkRefPtr::fObj : NULL; 17405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger } 17540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprivate: 17740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* fObj; 17840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}; 17940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 182