180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkWeakRefCnt_DEFINED
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkWeakRefCnt_DEFINED
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRefCnt.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThread.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** \class SkWeakRefCnt
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkWeakRefCnt is the base class for objects that may be shared by multiple
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    objects. When an existing strong owner wants to share a reference, it calls
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ref(). When a strong owner wants to release its reference, it calls
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unref(). When the shared object's strong reference count goes to zero as
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    the result of an unref() call, its (virtual) weak_dispose method is called.
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    It is an error for the destructor to be called explicitly (or via the
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    object going out of scope on the stack or calling delete) if
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    getRefCnt() > 1.
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    In addition to strong ownership, an owner may instead obtain a weak
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reference by calling weak_ref(). A call to weak_ref() must be balanced my a
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    call to weak_unref(). To obtain a strong reference from a weak reference,
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    call try_ref(). If try_ref() returns true, the owner's pointer is now also
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    a strong reference on which unref() must be called. Note that this does not
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    affect the original weak reference, weak_unref() must still be called. When
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    the weak reference count goes to zero, the object is deleted. While the
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    weak reference count is positive and the strong reference count is zero the
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    object still exists, but will be in the disposed state. It is up to the
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    object to define what this means.
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Note that a strong reference implicitly implies a weak reference. As a
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    result, it is allowable for the owner of a strong ref to call try_ref().
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    This will have the same effect as calling ref(), but may be more expensive.
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    Example:
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkWeakRefCnt myRef = strongRef.weak_ref();
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ... // strongRef.unref() may or may not be called
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (myRef.try_ref()) {
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        ... // use myRef
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        myRef.unref();
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // myRef is in the disposed state
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    myRef.weak_unref();
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SK_API SkWeakRefCnt : public SkRefCnt {
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_DECLARE_INST_COUNT(SkWeakRefCnt)
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Default construct, initializing the reference counts to 1.
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        The strong references collectively hold one weak reference. When the
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        strong reference count goes to zero, the collectively held weak
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        reference is released.
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Destruct, asserting that the weak reference count is 1.
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual ~SkWeakRefCnt() {
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fWeakCnt == 1);
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fWeakCnt = 0;
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Return the weak reference count.
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int32_t getWeakCnt() const { return fWeakCnt; }
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void validate() const {
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkRefCnt::validate();
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fWeakCnt > 0);
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Creates a strong reference from a weak reference, if possible. The
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        caller must already be an owner. If try_ref() returns true the owner
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        is in posession of an additional strong reference. Both the original
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        reference and new reference must be properly unreferenced. If try_ref()
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        returns false, no strong reference could be created and the owner's
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        reference is in the same state as before the call.
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool SK_WARN_UNUSED_RESULT try_ref() const {
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sk_atomic_conditional_inc(&fRefCnt) != 0) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Aquire barrier (L/SL), if not provided above.
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Prevents subsequent code from happening before the increment.
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_membar_aquire__after_atomic_conditional_inc();
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Increment the weak reference count. Must be balanced by a call to
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        weak_unref().
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void weak_ref() const {
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fRefCnt > 0);
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fWeakCnt > 0);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sk_atomic_inc(&fWeakCnt);  // No barrier required.
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Decrement the weak reference count. If the weak reference count is 1
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        before the decrement, then call delete on the object. Note that if this
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        is the case, then the object needs to have been allocated via new, and
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        not on the stack.
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void weak_unref() const {
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(fWeakCnt > 0);
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // Release barrier (SL/S), if not provided below.
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (sk_atomic_dec(&fWeakCnt) == 1) {
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Aquire barrier (L/SL), if not provided above.
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // Prevents code in destructor from happening before the decrement.
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            sk_membar_aquire__after_atomic_dec();
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_DEBUG
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // so our destructor won't complain
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fWeakCnt = 1;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkRefCnt::internal_dispose();
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Returns true if there are no strong references to the object. When this
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        is the case all future calls to try_ref() will return false.
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool weak_expired() const {
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return fRefCnt == 0;
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprotected:
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Called when the strong reference count goes to zero. This allows the
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        object to free any resources it may be holding. Weak references may
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        still exist and their level of allowed access to the object is defined
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        by the object's class.
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void weak_dispose() const {
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /** Called when the strong reference count goes to zero. Calls weak_dispose
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        on the object and releases the implicit weak reference held
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        collectively by the strong references.
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    */
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    virtual void internal_dispose() const SK_OVERRIDE {
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        weak_dispose();
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        weak_unref();
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    mutable int32_t fWeakCnt;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    typedef SkRefCnt INHERITED;
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
160