SkWeakRefCntmyRef=strongRef.weak_ref(); ...// strongRef.unref() may or may not be called if(myRef.try_ref()){ ...// use myRef myRef.unref(); }else{ // myRef is in the disposed state } myRef.weak_unref();
*/ class SK_API SkWeakRefCnt : public SkRefCnt { public: /** Default construct, initializing the reference counts to 1. Thestrongreferencescollectivelyholdoneweakreference.Whenthe strongreferencecountgoestozero,thecollectivelyheldweak referenceisreleased.
*/
SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}
/** Destruct, asserting that the weak reference count is 1.
*/
~SkWeakRefCnt() override { #ifdef SK_DEBUG
SkASSERT(getWeakCnt() == 1);
fWeakCnt.store(0, std::memory_order_relaxed); #endif
}
private: /** If fRefCnt is 0, returns 0. *OtherwiseincrementsfRefCnt,acquires,andreturnstheoldvalue.
*/
int32_t atomic_conditional_acquire_strong_ref() const {
int32_t prev = fRefCnt.load(std::memory_order_relaxed); do { if (0 == prev) { break;
}
} while(!fRefCnt.compare_exchange_weak(prev, prev+1, std::memory_order_acquire,
std::memory_order_relaxed)); return prev;
}
public: /** Creates a strong reference from a weak reference, if possible. The callermustalreadybeanowner.Iftry_ref()returnstruetheowner isinposessionofanadditionalstrongreference.Boththeoriginal referenceandnewreferencemustbeproperlyunreferenced.Iftry_ref() returnsfalse,nostrongreferencecouldbecreatedandtheowner's referenceisinthesamestateasbeforethecall.
*/
[[nodiscard]] bool try_ref() const { if (atomic_conditional_acquire_strong_ref() != 0) { // Acquire barrier (L/SL), if not provided above. // Prevents subsequent code from happening before the increment. returntrue;
} returnfalse;
}
/** Increment the weak reference count. Must be balanced by a call to weak_unref().
*/ void weak_ref() const {
SkASSERT(getRefCnt() > 0);
SkASSERT(getWeakCnt() > 0); // No barrier required.
(void)fWeakCnt.fetch_add(+1, std::memory_order_relaxed);
}
/** Decrement the weak reference count. If the weak reference count is 1 beforethedecrement,thencalldeleteontheobject.Notethatifthis isthecase,thentheobjectneedstohavebeenallocatedvianew,and notonthestack.
*/ void weak_unref() const {
SkASSERT(getWeakCnt() > 0); // A release here acts in place of all releases we "should" have been doing in ref(). if (1 == fWeakCnt.fetch_add(-1, std::memory_order_acq_rel)) { // Like try_ref(), the acquire is only needed on success, to make sure // code in internal_dispose() doesn't happen before the decrement. #ifdef SK_DEBUG // so our destructor won't complain
fWeakCnt.store(1, std::memory_order_relaxed); #endif this->INHERITED::internal_dispose();
}
}
/** Returns true if there are no strong references to the object. When this isthecaseallfuturecallstotry_ref()willreturnfalse.
*/ bool weak_expired() const { return fRefCnt.load(std::memory_order_relaxed) == 0;
}
protected: /** Called when the strong reference count goes to zero. This allows the objecttofreeanyresourcesitmaybeholding.Weakreferencesmay stillexistandtheirlevelofallowedaccesstotheobjectisdefined bytheobject'sclass.
*/ virtualvoid weak_dispose() const {
}
private: /** Called when the strong reference count goes to zero. Calls weak_dispose ontheobjectandreleasestheimplicitweakreferenceheld collectivelybythestrongreferences.
*/ void internal_dispose() const override {
weak_dispose();
weak_unref();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.