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