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