SkRefCnt.h revision 40528743dbb9ce7f39f093e0cdc47849ac8887cf
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * you may not use this file except in compliance with the License. 60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * You may obtain a copy of the License at 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * See the License for the specific language governing permissions and 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * limitations under the License. 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkRefCnt_DEFINED 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRefCnt_DEFINED 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h" 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** \class SkRefCnt 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt is the base class for objects that may be shared by multiple 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project objects. When a new owner wants a reference, it calls ref(). When an owner 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project wants to release its reference, it calls unref(). When the shared object's 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project reference count goes to zero as the result of an unref() call, its (virtual) 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project destructor is called. It is an error for the destructor to be called 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project explicitly (or via the object going out of scope on the stack or calling 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project delete) if getRefCnt() > 1. 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkRefCnt : SkNoncopyable { 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Default construct, initializing the reference count to 1. 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt() : fRefCnt(1) {} 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Destruct, asserting that the reference count is 1. 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project virtual ~SkRefCnt() { SkASSERT(fRefCnt == 1); } 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Return the reference count. 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int32_t getRefCnt() const { return fRefCnt; } 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Increment the reference count. Must be balanced by a call to unref(). 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void ref() const { 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fRefCnt > 0); 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_atomic_inc(&fRefCnt); 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** Decrement the reference count. If the reference count is 1 before the 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project decrement, then call delete on the object. Note that if this is the 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case, then the object needs to have been allocated via new, and not on 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project the stack. 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void unref() const { 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fRefCnt > 0); 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (sk_atomic_dec(&fRefCnt) == 1) { 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRefCnt = 1; // so our destructor won't complain 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDELETE(this); 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mutable int32_t fRefCnt; 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** \class SkAutoUnref 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoUnref is a stack-helper class that will automatically call unref() on 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project the object it points to when the SkAutoUnref object goes out of scope. 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project If obj is null, do nothing. 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkAutoUnref : SkNoncopyable { 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoUnref(SkRefCnt* obj) : fObj(obj) {} 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ~SkAutoUnref(); 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt* get() const { return fObj; } 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** If the hosted object is null, do nothing and return false, else call 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ref() on it and return true 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool ref(); 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** If the hosted object is null, do nothing and return false, else call 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unref() on it, set its reference to null, and return true 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool unref(); 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /** If the hosted object is null, do nothing and return NULL, else call 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unref() on it, set its reference to null, and return the object 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt* detach(); 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRefCnt* fObj; 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project null in on each side of the assignment, and ensuring that ref() is called 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project before unref(), in case the two pointers point to the same object. 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRefCnt_SafeAssign(dst, src) \ 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { \ 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (src) src->ref(); \ 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dst) dst->unref(); \ 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst = src; \ 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (0) 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 115dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 116dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed/** Check if the argument is non-null, and if so, call obj->ref() 117dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed */ 118dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reedtemplate <typename T> static inline void SkSafeRef(T* obj) { 119dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed if (obj) { 120dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed obj->ref(); 121dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed } 122dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed} 123dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 124dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed/** Check if the argument is non-null, and if so, call obj->unref() 125dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed */ 126dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reedtemplate <typename T> static inline void SkSafeUnref(T* obj) { 127dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed if (obj) { 128dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed obj->unref(); 129dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed } 130dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed} 131dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to 13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger a SkRefCnt (or subclass) object. 13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */ 13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergertemplate <typename T> class SkRefPtr { 13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic: 13740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr() : fObj(NULL) {} 13840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); } 13940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); } 14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger ~SkRefPtr() { SkSafeUnref(fObj); } 14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 14240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr& operator=(const SkRefPtr& rp) { 14340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefCnt_SafeAssign(fObj, rp.fObj); 14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return *this; 14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr& operator=(T* obj) { 14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefCnt_SafeAssign(fObj, obj); 14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return *this; 14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool operator==(const SkRefPtr& rp) const { return fObj == rp.fObj; } 15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool operator==(const T* obj) const { return fObj == obj; } 15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool operator!=(const SkRefPtr& rp) const { return fObj != rp.fObj; } 15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool operator!=(const T* obj) const { return fObj != obj; } 15540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* get() const { return fObj; } 15740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T& operator*() const { return *fObj; } 15840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* operator->() const { return fObj; } 15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool operator!() const { return !fObj; } 16040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger typedef T* SkRefPtr::*unspecified_bool_type; 16240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger operator unspecified_bool_type() const { return fObj ? &SkRefPtr::fObj : NULL; } 16340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprivate: 16540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* fObj; 16640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}; 16740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergertemplate <typename T> 16940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerinline bool operator==(T* obj, const SkRefPtr<T>& rp) { 17040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return obj == rp.get(); 17140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 17240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergertemplate <typename T> 17440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerinline bool operator!=(T* obj, const SkRefPtr<T>& rp) { 17540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return obj != rp.get(); 17640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 17740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 180