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