SkRefCnt.h revision 6d2533ebd2ad5168d08f5a83e681881c0d533949
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkRefCnt_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkRefCnt_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h"
14977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com#include "SkInstCnt.h"
1591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com#include "SkTemplates.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
176d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#ifdef SK_REF_CNT_BASE_INCLUDE
186d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#include SK_REF_CNT_BASE_INCLUDE
196d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#else
206d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org/** \class SkRefCntBase
216d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org
226d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    Default implementation of SkRefCntBase. The base class' contract is to
236d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    provide an implementation of aboutToRef. Embedders of skia can specify
246d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    an alternate implementation by setting SK_REF_CNT_BASE_INCLUDE. This is
256d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    useful for adding debug run-time checks to enforce certain usage patterns.
266d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org*/
276d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.orgclass SK_API SkRefCntBase {
286d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.orgpublic:
296d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    void aboutToRef() const {}
306d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org};
316d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org#endif
326d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkRefCnt
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt is the base class for objects that may be shared by multiple
36a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    objects. When an existing owner wants to share a reference, it calls ref().
37a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    When an owner wants to release its reference, it calls unref(). When the
38a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    shared object's reference count goes to zero as the result of an unref()
39a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    call, its (virtual) destructor is called. It is an error for the
40a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    destructor to be called explicitly (or via the object going out of scope on
41a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    the stack or calling delete) if getRefCnt() > 1.
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
436d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.orgclass SK_API SkRefCnt : public SkRefCntBase {
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com    SK_DECLARE_INST_COUNT_ROOT(SkRefCnt)
46977b9c8af3ef1b9a2fa2a0037cf3734cf2ba13d9robertphillips@google.com
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Default construct, initializing the reference count to 1.
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRefCnt() : fRefCnt(1) {}
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
51a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    /** Destruct, asserting that the reference count is 1.
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
534c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com    virtual ~SkRefCnt() {
544c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#ifdef SK_DEBUG
554c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com        SkASSERT(fRefCnt == 1);
564c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com        fRefCnt = 0;    // illegal value, to catch us if we reuse after delete
574c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com#endif
584c888aae25c1f6a420caceec7c42736ba6ddad3dreed@google.com    }
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
60f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    /** Return the reference count. Use only for debugging. */
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int32_t getRefCnt() const { return fRefCnt; }
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
63f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    /** Returns true if the caller is the only owner.
64f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com     *  Ensures that all previous owner's actions are complete.
65f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com     */
66f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    bool unique() const {
67f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        bool const unique = (1 == fRefCnt);
68f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        if (unique) {
69f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com            // Aquire barrier (L/SL), if not provided by load of fRefCnt.
70f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com            // Prevents user's 'unique' code from happening before decrements.
71f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com            //TODO: issue the barrier.
72f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        }
73f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com        return unique;
74f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    }
75f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Increment the reference count. Must be balanced by a call to unref().
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void ref() const {
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRefCnt > 0);
806d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org        this->INHERITED::aboutToRef();
81a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        sk_atomic_inc(&fRefCnt);  // No barrier required.
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Decrement the reference count. If the reference count is 1 before the
85a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        decrement, then delete the object. Note that if this is the case, then
86a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        the object needs to have been allocated via new, and not on the stack.
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    */
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void unref() const {
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRefCnt > 0);
90a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        // Release barrier (SL/S), if not provided below.
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (sk_atomic_dec(&fRefCnt) == 1) {
92a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com            // Aquire barrier (L/SL), if not provided above.
93a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com            // Prevents code in dispose from happening before the decrement.
94a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com            sk_membar_aquire__after_atomic_dec();
95a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com            internal_dispose();
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9903087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#ifdef SK_DEBUG
1007f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    void validate() const {
1017f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        SkASSERT(fRefCnt > 0);
1027f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
10303087072483378a43f7b3f7a47944614187275ebrobertphillips@google.com#endif
1047f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1059f0af0a285addbeb55db5dd92c3a3b92c144532freed@google.com    /**
10639095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org     * Alias for unref(), for compatibility with WTF::RefPtr.
10739095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org     */
10839095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org    void deref() { this->unref(); }
10939095b9d14b2a2ad7acd1e24b9ebbc20cf7eb4e1commit-bot@chromium.org
110f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprotected:
111f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    /**
112f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  Allow subclasses to call this if they've overridden internal_dispose
113f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  so they can reset fRefCnt before the destructor is called. Should only
114f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  be called right before calling through to inherited internal_dispose()
115f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  or before calling the destructor.
116f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     */
117f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    void internal_dispose_restore_refcnt_to_1() const {
118a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#ifdef SK_DEBUG
119f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com        SkASSERT(0 == fRefCnt);
120a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        fRefCnt = 1;
121a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com#endif
122f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    }
123f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com
124f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.comprivate:
125f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    /**
1266d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org     *  Make SkRefCnt non-copyable.
1276d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org     */
1286d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    SkRefCnt(const SkRefCnt&);
1296d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    SkRefCnt& operator=(const SkRefCnt&);
1306d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org
1316d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    /**
132f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     *  Called when the ref count goes to 0.
133f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com     */
134f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com    virtual void internal_dispose() const {
135f79430350d9f06a72b307af879d7f3bdec7ff706reed@google.com        this->internal_dispose_restore_refcnt_to_1();
136a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com        SkDELETE(this);
137a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    }
13815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
139f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    // The following friends are those which override internal_dispose()
140f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    // and conditionally call SkRefCnt::internal_dispose().
141f64c6842c15e1ba126639be7578e4642cb396987bungeman@google.com    friend class GrTexture;
142a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com    friend class SkWeakRefCnt;
143a02bc1519cf49afa31fb38bed097dd5014880d04bungeman@google.com
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    mutable int32_t fRefCnt;
1454d73ac22a1b99402fc8cff78a4eb4b27aa8fe019robertphillips@google.com
1466d2533ebd2ad5168d08f5a83e681881c0d533949commit-bot@chromium.org    typedef SkRefCntBase INHERITED;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1497f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com///////////////////////////////////////////////////////////////////////////////
1507f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1517f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for
1527f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    null in on each side of the assignment, and ensuring that ref() is called
1537f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    before unref(), in case the two pointers point to the same object.
1547f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1557f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com#define SkRefCnt_SafeAssign(dst, src)   \
1567f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    do {                                \
1577f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        if (src) src->ref();            \
1587f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        if (dst) dst->unref();          \
1597f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        dst = src;                      \
1607f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    } while (0)
1617f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1627f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1631fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Call obj->ref() and return obj. The obj must not be NULL.
1647f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1651fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkRef(T* obj) {
1661fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    SkASSERT(obj);
1671fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    obj->ref();
1681fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    return obj;
1691fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com}
1701fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com
1711fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com/** Check if the argument is non-null, and if so, call obj->ref() and return obj.
1721fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com */
1731fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.comtemplate <typename T> static inline T* SkSafeRef(T* obj) {
1747f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    if (obj) {
1757f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        obj->ref();
1767f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
1771fd201b9dfc739b7a615fdc1eb64dbe136e7cf76bungeman@google.com    return obj;
1787f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}
1797f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
1807f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com/** Check if the argument is non-null, and if so, call obj->unref()
1817f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com */
1827f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comtemplate <typename T> static inline void SkSafeUnref(T* obj) {
1837f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    if (obj) {
1847f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com        obj->unref();
1857f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    }
1867f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com}
1877f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
188a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.orgtemplate<typename T> static inline void SkSafeSetNull(T*& obj) {
189a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    if (NULL != obj) {
190a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org        obj->unref();
191a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org        obj = NULL;
192a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    }
193a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org}
194a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org
1957f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com///////////////////////////////////////////////////////////////////////////////
1967f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com
197a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com/**
19891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com *  Utility class that simply unref's its argument in the destructor.
199a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com */
20091208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comtemplate <typename T> class SkAutoTUnref : SkNoncopyable {
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
20291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    explicit SkAutoTUnref(T* obj = NULL) : fObj(obj) {}
20391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    ~SkAutoTUnref() { SkSafeUnref(fObj); }
204a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com
205a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com    T* get() const { return fObj; }
206a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com
2072863f082f2524ebae9e69f382b50065189912b47reed@google.com    T* reset(T* obj) {
20868d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com        SkSafeUnref(fObj);
20968d6bb0c119141b0c8637d0b1b3c8b73c7026933reed@google.com        fObj = obj;
2102863f082f2524ebae9e69f382b50065189912b47reed@google.com        return obj;
211a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com    }
212a44f7003e5f9d1353bc9274268fb5302e69fc94absalomon@google.com
2131dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    void swap(SkAutoTUnref* other) {
2141dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        T* tmp = fObj;
2151dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        fObj = other->fObj;
2161dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com        other->fObj = tmp;
2171dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com    }
2181dfe88e00aeddf20690fd2469fd17e43f670ee3absalomon@google.com
219a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com    /**
220a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com     *  Return the hosted object (which may be null), transferring ownership.
221a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com     *  The reference count is not modified, and the internal ptr is set to NULL
222a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com     *  so unref() will not be called in our destructor. A subsequent call to
223a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com     *  detach() will do nothing and return null.
224a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com     */
225a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com    T* detach() {
226a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com        T* obj = fObj;
227a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com        fObj = NULL;
228a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com        return obj;
229a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com    }
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
231e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com    /**
2326f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com     *  BlockRef<B> is a type which inherits from B, cannot be created,
2336f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com     *  cannot be deleted, and makes ref and unref private.
234e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com     */
23504640299dc0d71752295a630d58f6160642f3c8ebungeman@google.com    template<typename B> class BlockRef : public B {
236e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com    private:
237e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com        BlockRef();
2386f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com        ~BlockRef();
239e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com        void ref() const;
240e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com        void unref() const;
241e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com    };
2421448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com
24391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    /** If T is const, the type returned from operator-> will also be const. */
24491208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    typedef typename SkTConstType<BlockRef<T>, SkTIsConst<T>::value>::type BlockRefType;
2451448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com
246e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com    /**
247e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com     *  SkAutoTUnref assumes ownership of the ref. As a result, it is an error
248e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com     *  for the user to ref or unref through SkAutoTUnref. Therefore
249e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com     *  SkAutoTUnref::operator-> returns BlockRef<T>*. This prevents use of
250e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com     *  skAutoTUnrefInstance->ref() and skAutoTUnrefInstance->unref().
251e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com     */
25291208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    BlockRefType *operator->() const {
25391208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com        return static_cast<BlockRefType*>(fObj);
254e70f798ebca1a66f0b568fa46065ebbad9a13b2fbungeman@google.com    }
25591208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    operator T*() { return fObj; }
2561448cf8cb6c6cd4866f7c71bf32ad6bca5d683d1bsalomon@google.com
25791208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.comprivate:
25891208922687a33df1d5253928b8d5d7d4685c7acbungeman@google.com    T*  fObj;
259a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com};
260a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com
261a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.comclass SkAutoUnref : public SkAutoTUnref<SkRefCnt> {
262a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.compublic:
263a67573e25faa81ea65e6fc368f66d3f0c0a5f189reed@google.com    SkAutoUnref(SkRefCnt* obj) : SkAutoTUnref<SkRefCnt>(obj) {}
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2667f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comclass SkAutoRef : SkNoncopyable {
2677f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.compublic:
2687f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    SkAutoRef(SkRefCnt* obj) : fObj(obj) { SkSafeRef(obj); }
2697f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    ~SkAutoRef() { SkSafeUnref(fObj); }
2707f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.comprivate:
2717f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com    SkRefCnt* fObj;
2727f6d6d4571c0682c81f8508ac4862b2dfea20aecreed@google.com};
273149e2f6159a797989f6f0fa93ecfaa66cdd55c40reed@android.com
2742b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com/** Wrapper class for SkRefCnt pointers. This manages ref/unref of a pointer to
2752b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    a SkRefCnt (or subclass) object.
2762b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com */
2772b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.comtemplate <typename T> class SkRefPtr {
2782b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.compublic:
2792b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    SkRefPtr() : fObj(NULL) {}
2802b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    SkRefPtr(T* obj) : fObj(obj) { SkSafeRef(fObj); }
2812b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    SkRefPtr(const SkRefPtr& o) : fObj(o.fObj) { SkSafeRef(fObj); }
2822b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    ~SkRefPtr() { SkSafeUnref(fObj); }
2832b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com
2842b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    SkRefPtr& operator=(const SkRefPtr& rp) {
2852b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com        SkRefCnt_SafeAssign(fObj, rp.fObj);
2862b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com        return *this;
2872b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    }
2882b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    SkRefPtr& operator=(T* obj) {
2892b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com        SkRefCnt_SafeAssign(fObj, obj);
2902b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com        return *this;
2912b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    }
2922b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com
2932b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    T* get() const { return fObj; }
2942b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    T& operator*() const { return *fObj; }
2952b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    T* operator->() const { return fObj; }
2962b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com
2972b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    typedef T* SkRefPtr::*unspecified_bool_type;
2982b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    operator unspecified_bool_type() const {
2992b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com        return fObj ? &SkRefPtr::fObj : NULL;
3002b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    }
3012b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com
3022b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.comprivate:
3032b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com    T* fObj;
3042b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com};
3052b4e5445d2097cd4c849a2d96df9b6075a725c5arobertphillips@google.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
307