gfx/skia/trunk/include/core/SkWeakRefCnt.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/core/SkWeakRefCnt.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,161 @@
     1.4 +/*
     1.5 + * Copyright 2012 Google Inc.
     1.6 + *
     1.7 + * Use of this source code is governed by a BSD-style license that can be
     1.8 + * found in the LICENSE file.
     1.9 + */
    1.10 +
    1.11 +#ifndef SkWeakRefCnt_DEFINED
    1.12 +#define SkWeakRefCnt_DEFINED
    1.13 +
    1.14 +#include "SkRefCnt.h"
    1.15 +#include "SkThread.h"
    1.16 +
    1.17 +/** \class SkWeakRefCnt
    1.18 +
    1.19 +    SkWeakRefCnt is the base class for objects that may be shared by multiple
    1.20 +    objects. When an existing strong owner wants to share a reference, it calls
    1.21 +    ref(). When a strong owner wants to release its reference, it calls
    1.22 +    unref(). When the shared object's strong reference count goes to zero as
    1.23 +    the result of an unref() call, its (virtual) weak_dispose method is called.
    1.24 +    It is an error for the destructor to be called explicitly (or via the
    1.25 +    object going out of scope on the stack or calling delete) if
    1.26 +    getRefCnt() > 1.
    1.27 +
    1.28 +    In addition to strong ownership, an owner may instead obtain a weak
    1.29 +    reference by calling weak_ref(). A call to weak_ref() must be balanced by a
    1.30 +    call to weak_unref(). To obtain a strong reference from a weak reference,
    1.31 +    call try_ref(). If try_ref() returns true, the owner's pointer is now also
    1.32 +    a strong reference on which unref() must be called. Note that this does not
    1.33 +    affect the original weak reference, weak_unref() must still be called. When
    1.34 +    the weak reference count goes to zero, the object is deleted. While the
    1.35 +    weak reference count is positive and the strong reference count is zero the
    1.36 +    object still exists, but will be in the disposed state. It is up to the
    1.37 +    object to define what this means.
    1.38 +
    1.39 +    Note that a strong reference implicitly implies a weak reference. As a
    1.40 +    result, it is allowable for the owner of a strong ref to call try_ref().
    1.41 +    This will have the same effect as calling ref(), but may be more expensive.
    1.42 +
    1.43 +    Example:
    1.44 +
    1.45 +    SkWeakRefCnt myRef = strongRef.weak_ref();
    1.46 +    ... // strongRef.unref() may or may not be called
    1.47 +    if (myRef.try_ref()) {
    1.48 +        ... // use myRef
    1.49 +        myRef.unref();
    1.50 +    } else {
    1.51 +        // myRef is in the disposed state
    1.52 +    }
    1.53 +    myRef.weak_unref();
    1.54 +*/
    1.55 +class SK_API SkWeakRefCnt : public SkRefCnt {
    1.56 +public:
    1.57 +    SK_DECLARE_INST_COUNT(SkWeakRefCnt)
    1.58 +
    1.59 +    /** Default construct, initializing the reference counts to 1.
    1.60 +        The strong references collectively hold one weak reference. When the
    1.61 +        strong reference count goes to zero, the collectively held weak
    1.62 +        reference is released.
    1.63 +    */
    1.64 +    SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}
    1.65 +
    1.66 +    /** Destruct, asserting that the weak reference count is 1.
    1.67 +    */
    1.68 +    virtual ~SkWeakRefCnt() {
    1.69 +#ifdef SK_DEBUG
    1.70 +        SkASSERT(fWeakCnt == 1);
    1.71 +        fWeakCnt = 0;
    1.72 +#endif
    1.73 +    }
    1.74 +
    1.75 +    /** Return the weak reference count.
    1.76 +    */
    1.77 +    int32_t getWeakCnt() const { return fWeakCnt; }
    1.78 +
    1.79 +#ifdef SK_DEBUG
    1.80 +    void validate() const {
    1.81 +        this->INHERITED::validate();
    1.82 +        SkASSERT(fWeakCnt > 0);
    1.83 +    }
    1.84 +#endif
    1.85 +
    1.86 +    /** Creates a strong reference from a weak reference, if possible. The
    1.87 +        caller must already be an owner. If try_ref() returns true the owner
    1.88 +        is in posession of an additional strong reference. Both the original
    1.89 +        reference and new reference must be properly unreferenced. If try_ref()
    1.90 +        returns false, no strong reference could be created and the owner's
    1.91 +        reference is in the same state as before the call.
    1.92 +    */
    1.93 +    bool SK_WARN_UNUSED_RESULT try_ref() const {
    1.94 +        if (sk_atomic_conditional_inc(&fRefCnt) != 0) {
    1.95 +            // Acquire barrier (L/SL), if not provided above.
    1.96 +            // Prevents subsequent code from happening before the increment.
    1.97 +            sk_membar_acquire__after_atomic_conditional_inc();
    1.98 +            return true;
    1.99 +        }
   1.100 +        return false;
   1.101 +    }
   1.102 +
   1.103 +    /** Increment the weak reference count. Must be balanced by a call to
   1.104 +        weak_unref().
   1.105 +    */
   1.106 +    void weak_ref() const {
   1.107 +        SkASSERT(fRefCnt > 0);
   1.108 +        SkASSERT(fWeakCnt > 0);
   1.109 +        sk_atomic_inc(&fWeakCnt);  // No barrier required.
   1.110 +    }
   1.111 +
   1.112 +    /** Decrement the weak reference count. If the weak reference count is 1
   1.113 +        before the decrement, then call delete on the object. Note that if this
   1.114 +        is the case, then the object needs to have been allocated via new, and
   1.115 +        not on the stack.
   1.116 +    */
   1.117 +    void weak_unref() const {
   1.118 +        SkASSERT(fWeakCnt > 0);
   1.119 +        // Release barrier (SL/S), if not provided below.
   1.120 +        if (sk_atomic_dec(&fWeakCnt) == 1) {
   1.121 +            // Acquire barrier (L/SL), if not provided above.
   1.122 +            // Prevents code in destructor from happening before the decrement.
   1.123 +            sk_membar_acquire__after_atomic_dec();
   1.124 +#ifdef SK_DEBUG
   1.125 +            // so our destructor won't complain
   1.126 +            fWeakCnt = 1;
   1.127 +#endif
   1.128 +            this->INHERITED::internal_dispose();
   1.129 +        }
   1.130 +    }
   1.131 +
   1.132 +    /** Returns true if there are no strong references to the object. When this
   1.133 +        is the case all future calls to try_ref() will return false.
   1.134 +    */
   1.135 +    bool weak_expired() const {
   1.136 +        return fRefCnt == 0;
   1.137 +    }
   1.138 +
   1.139 +protected:
   1.140 +    /** Called when the strong reference count goes to zero. This allows the
   1.141 +        object to free any resources it may be holding. Weak references may
   1.142 +        still exist and their level of allowed access to the object is defined
   1.143 +        by the object's class.
   1.144 +    */
   1.145 +    virtual void weak_dispose() const {
   1.146 +    }
   1.147 +
   1.148 +private:
   1.149 +    /** Called when the strong reference count goes to zero. Calls weak_dispose
   1.150 +        on the object and releases the implicit weak reference held
   1.151 +        collectively by the strong references.
   1.152 +    */
   1.153 +    virtual void internal_dispose() const SK_OVERRIDE {
   1.154 +        weak_dispose();
   1.155 +        weak_unref();
   1.156 +    }
   1.157 +
   1.158 +    /* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */
   1.159 +    mutable int32_t fWeakCnt;
   1.160 +
   1.161 +    typedef SkRefCnt INHERITED;
   1.162 +};
   1.163 +
   1.164 +#endif

mercurial