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