SkRefCnt.h revision 137a4ca42423bbb6d683067ea544c9a48f18f06c
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*/ 32137a4ca42423bbb6d683067ea544c9a48f18f06cDerek Sollenbergerclass SK_API 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 7005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger/** 7105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * Utility class that simply unref's its argument in the destructor. 7205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */ 7305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergertemplate <typename T> class SkAutoTUnref : SkNoncopyable { 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 7505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger SkAutoTUnref(T* obj) : fObj(obj) {} 7605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger ~SkAutoTUnref() { SkSafeUnref(fObj); } 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* get() const { return fObj; } 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger /** 8105b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * Return the hosted object (which may be null), transferring ownership. 8205b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * The reference count is not modified, and the internal ptr is set to NULL 8305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * so unref() will not be called in our destructor. A subsequent call to 8405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger * detach() will do nothing and return null. 8505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger */ 8605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* detach() { 8705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* obj = fObj; 8805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger fObj = NULL; 8905b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger return obj; 9005b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger } 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 9305b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger T* fObj; 9405b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger}; 9505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger 9605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> { 9705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenbergerpublic: 9805b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {} 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project null in on each side of the assignment, and ensuring that ref() is called 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project before unref(), in case the two pointers point to the same object. 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkRefCnt_SafeAssign(dst, src) \ 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { \ 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (src) src->ref(); \ 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dst) dst->unref(); \ 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst = src; \ 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (0) 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 114dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 115dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed/** Check if the argument is non-null, and if so, call obj->ref() 116dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed */ 117dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reedtemplate <typename T> static inline void SkSafeRef(T* obj) { 118dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed if (obj) { 119dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed obj->ref(); 120dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed } 121dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed} 122dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 123dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed/** Check if the argument is non-null, and if so, call obj->unref() 124dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed */ 125dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reedtemplate <typename T> static inline void SkSafeUnref(T* obj) { 126dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed if (obj) { 127dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed obj->unref(); 128dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed } 129dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed} 130dab163f0b2658c2dba48839e72f81d3d8ee0ae8bMike Reed 13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to 13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger a SkRefCnt (or subclass) object. 13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger */ 13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergertemplate <typename T> class SkRefPtr { 13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic: 13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr() : fObj(NULL) {} 13740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); } 13840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); } 13940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger ~SkRefPtr() { SkSafeUnref(fObj); } 14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr& operator=(const SkRefPtr& rp) { 14240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefCnt_SafeAssign(fObj, rp.fObj); 14340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return *this; 14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefPtr& operator=(T* obj) { 14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkRefCnt_SafeAssign(fObj, obj); 14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return *this; 14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* get() const { return fObj; } 15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T& operator*() const { return *fObj; } 15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* operator->() const { return fObj; } 15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger typedef T* SkRefPtr::*unspecified_bool_type; 15505b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger operator unspecified_bool_type() const { 15605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger return fObj ? &SkRefPtr::fObj : NULL; 15705b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger } 15840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprivate: 16040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger T* fObj; 16140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}; 16240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 165