LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/private - SkWeakRefCnt.h (source / functions) Hit Total Coverage
Test: output.info Lines: 1 19 5.3 %
Date: 2017-07-14 16:53:18 Functions: 1 7 14.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkWeakRefCnt_DEFINED
       9             : #define SkWeakRefCnt_DEFINED
      10             : 
      11             : #include "SkRefCnt.h"
      12             : #include <atomic>
      13             : 
      14             : /** \class SkWeakRefCnt
      15             : 
      16             :     SkWeakRefCnt is the base class for objects that may be shared by multiple
      17             :     objects. When an existing strong owner wants to share a reference, it calls
      18             :     ref(). When a strong owner wants to release its reference, it calls
      19             :     unref(). When the shared object's strong reference count goes to zero as
      20             :     the result of an unref() call, its (virtual) weak_dispose method is called.
      21             :     It is an error for the destructor to be called explicitly (or via the
      22             :     object going out of scope on the stack or calling delete) if
      23             :     getRefCnt() > 1.
      24             : 
      25             :     In addition to strong ownership, an owner may instead obtain a weak
      26             :     reference by calling weak_ref(). A call to weak_ref() must be balanced by a
      27             :     call to weak_unref(). To obtain a strong reference from a weak reference,
      28             :     call try_ref(). If try_ref() returns true, the owner's pointer is now also
      29             :     a strong reference on which unref() must be called. Note that this does not
      30             :     affect the original weak reference, weak_unref() must still be called. When
      31             :     the weak reference count goes to zero, the object is deleted. While the
      32             :     weak reference count is positive and the strong reference count is zero the
      33             :     object still exists, but will be in the disposed state. It is up to the
      34             :     object to define what this means.
      35             : 
      36             :     Note that a strong reference implicitly implies a weak reference. As a
      37             :     result, it is allowable for the owner of a strong ref to call try_ref().
      38             :     This will have the same effect as calling ref(), but may be more expensive.
      39             : 
      40             :     Example:
      41             : 
      42             :     SkWeakRefCnt myRef = strongRef.weak_ref();
      43             :     ... // strongRef.unref() may or may not be called
      44             :     if (myRef.try_ref()) {
      45             :         ... // use myRef
      46             :         myRef.unref();
      47             :     } else {
      48             :         // myRef is in the disposed state
      49             :     }
      50             :     myRef.weak_unref();
      51             : */
      52             : class SK_API SkWeakRefCnt : public SkRefCnt {
      53             : public:
      54             :     /** Default construct, initializing the reference counts to 1.
      55             :         The strong references collectively hold one weak reference. When the
      56             :         strong reference count goes to zero, the collectively held weak
      57             :         reference is released.
      58             :     */
      59           2 :     SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}
      60             : 
      61             :     /** Destruct, asserting that the weak reference count is 1.
      62             :     */
      63           0 :     ~SkWeakRefCnt() override {
      64             : #ifdef SK_DEBUG
      65           0 :         SkASSERT(getWeakCnt() == 1);
      66           0 :         fWeakCnt.store(0, std::memory_order_relaxed);
      67             : #endif
      68           0 :     }
      69             : 
      70             : #ifdef SK_DEBUG
      71             :     /** Return the weak reference count. */
      72           0 :     int32_t getWeakCnt() const {
      73           0 :         return fWeakCnt.load(std::memory_order_relaxed);
      74             :     }
      75             : 
      76             :     void validate() const {
      77             :         this->INHERITED::validate();
      78             :         SkASSERT(getWeakCnt() > 0);
      79             :     }
      80             : #endif
      81             : 
      82             : private:
      83             :     /** If fRefCnt is 0, returns 0.
      84             :      *  Otherwise increments fRefCnt, acquires, and returns the old value.
      85             :      */
      86             :     int32_t atomic_conditional_acquire_strong_ref() const {
      87             :         int32_t prev = fRefCnt.load(std::memory_order_relaxed);
      88             :         do {
      89             :             if (0 == prev) {
      90             :                 break;
      91             :             }
      92             :         } while(!fRefCnt.compare_exchange_weak(prev, prev+1, std::memory_order_acquire,
      93             :                                                              std::memory_order_relaxed));
      94             :         return prev;
      95             :     }
      96             : 
      97             : public:
      98             :     /** Creates a strong reference from a weak reference, if possible. The
      99             :         caller must already be an owner. If try_ref() returns true the owner
     100             :         is in posession of an additional strong reference. Both the original
     101             :         reference and new reference must be properly unreferenced. If try_ref()
     102             :         returns false, no strong reference could be created and the owner's
     103             :         reference is in the same state as before the call.
     104             :     */
     105             :     bool SK_WARN_UNUSED_RESULT try_ref() const {
     106             :         if (atomic_conditional_acquire_strong_ref() != 0) {
     107             :             // Acquire barrier (L/SL), if not provided above.
     108             :             // Prevents subsequent code from happening before the increment.
     109             :             return true;
     110             :         }
     111             :         return false;
     112             :     }
     113             : 
     114             :     /** Increment the weak reference count. Must be balanced by a call to
     115             :         weak_unref().
     116             :     */
     117             :     void weak_ref() const {
     118             :         SkASSERT(getRefCnt() > 0);
     119             :         SkASSERT(getWeakCnt() > 0);
     120             :         // No barrier required.
     121             :         (void)fWeakCnt.fetch_add(+1, std::memory_order_relaxed);
     122             :     }
     123             : 
     124             :     /** Decrement the weak reference count. If the weak reference count is 1
     125             :         before the decrement, then call delete on the object. Note that if this
     126             :         is the case, then the object needs to have been allocated via new, and
     127             :         not on the stack.
     128             :     */
     129           0 :     void weak_unref() const {
     130           0 :         SkASSERT(getWeakCnt() > 0);
     131             :         // A release here acts in place of all releases we "should" have been doing in ref().
     132           0 :         if (1 == fWeakCnt.fetch_add(-1, std::memory_order_acq_rel)) {
     133             :             // Like try_ref(), the acquire is only needed on success, to make sure
     134             :             // code in internal_dispose() doesn't happen before the decrement.
     135             : #ifdef SK_DEBUG
     136             :             // so our destructor won't complain
     137           0 :             fWeakCnt.store(1, std::memory_order_relaxed);
     138             : #endif
     139           0 :             this->INHERITED::internal_dispose();
     140             :         }
     141           0 :     }
     142             : 
     143             :     /** Returns true if there are no strong references to the object. When this
     144             :         is the case all future calls to try_ref() will return false.
     145             :     */
     146             :     bool weak_expired() const {
     147             :         return fRefCnt.load(std::memory_order_relaxed) == 0;
     148             :     }
     149             : 
     150             : protected:
     151             :     /** Called when the strong reference count goes to zero. This allows the
     152             :         object to free any resources it may be holding. Weak references may
     153             :         still exist and their level of allowed access to the object is defined
     154             :         by the object's class.
     155             :     */
     156           0 :     virtual void weak_dispose() const {
     157           0 :     }
     158             : 
     159             : private:
     160             :     /** Called when the strong reference count goes to zero. Calls weak_dispose
     161             :         on the object and releases the implicit weak reference held
     162             :         collectively by the strong references.
     163             :     */
     164           0 :     void internal_dispose() const override {
     165           0 :         weak_dispose();
     166           0 :         weak_unref();
     167           0 :     }
     168             : 
     169             :     /* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */
     170             :     mutable std::atomic<int32_t> fWeakCnt;
     171             : 
     172             :     typedef SkRefCnt INHERITED;
     173             : };
     174             : 
     175             : #endif

Generated by: LCOV version 1.13