Index: include/gpu/GrGpuResource.h |
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h |
index e2f23e02897939778db5531072a6a6498f974134..5a35ab794ab12aa9209c07e85b1a3b7687b7cd61 100644 |
--- a/include/gpu/GrGpuResource.h |
+++ b/include/gpu/GrGpuResource.h |
@@ -33,8 +33,15 @@ class GrResourceCache; |
* |
* The latter two ref types are private and intended only for Gr core code. |
* |
- * When an item is purgeable DERIVED:notifyIsPurgeable() will be called (static poly morphism using |
- * CRTP). GrIORef and GrGpuResource are separate classes for organizational reasons and to be |
+ * When all the ref/io counts reach zero DERIVED::notifyAllCntsAreZero() will be called (static poly |
+ * morphism using CRTP). Similarly when the ref (but not necessarily pending read/write) count |
+ * reaches 0 DERIVED::notifyRefCountIsZero() will be called. In the case when an unref() causes both |
+ * the ref cnt to reach zero and the other counts are zero, notifyRefCountIsZero() will be called |
+ * before notifyIsPurgeable(). Moreover, if notifyRefCountIsZero() returns false then |
+ * notifyAllRefCntsAreZero() won't be called at all. notifyRefCountIsZero() must return false if the |
+ * object may be deleted after notifyRefCntIsZero() returns. |
+ * |
+ * GrIORef and GrGpuResource are separate classes for organizational reasons and to be |
* able to give access via friendship to only the functions related to pending IO operations. |
*/ |
template <typename DERIVED> class GrIORef : public SkNoncopyable { |
@@ -52,8 +59,14 @@ public: |
void unref() const { |
this->validate(); |
- --fRefCnt; |
- this->didUnref(); |
+ |
+ if (!(--fRefCnt)) { |
+ if (!static_cast<const DERIVED*>(this)->notifyRefCountIsZero()) { |
+ return; |
+ } |
+ } |
+ |
+ this->didRemoveRefOrPendingIO(kRef_CntType); |
} |
void validate() const { |
@@ -68,6 +81,12 @@ public: |
protected: |
GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) { } |
+ enum CntType { |
+ kRef_CntType, |
+ kPendingRead_CntType, |
+ kPendingWrite_CntType, |
+ }; |
+ |
bool isPurgeable() const { return !this->internalHasRef() && !this->internalHasPendingIO(); } |
bool internalHasPendingRead() const { return SkToBool(fPendingReads); } |
@@ -85,7 +104,7 @@ private: |
void completedRead() const { |
this->validate(); |
--fPendingReads; |
- this->didUnref(); |
+ this->didRemoveRefOrPendingIO(kPendingRead_CntType); |
} |
void addPendingWrite() const { |
@@ -96,13 +115,13 @@ private: |
void completedWrite() const { |
this->validate(); |
--fPendingWrites; |
- this->didUnref(); |
+ this->didRemoveRefOrPendingIO(kPendingWrite_CntType); |
} |
private: |
- void didUnref() const { |
+ void didRemoveRefOrPendingIO(CntType cntTypeRemoved) const { |
if (0 == fPendingReads && 0 == fPendingWrites && 0 == fRefCnt) { |
- static_cast<const DERIVED*>(this)->notifyIsPurgeable(); |
+ static_cast<const DERIVED*>(this)->notifyAllCntsAreZero(cntTypeRemoved); |
} |
} |
@@ -271,7 +290,8 @@ private: |
// See comments in CacheAccess and ResourcePriv. |
void setUniqueKey(const GrUniqueKey&); |
void removeUniqueKey(); |
- void notifyIsPurgeable() const; |
+ void notifyAllCntsAreZero(CntType) const; |
+ bool notifyRefCountIsZero() const; |
void removeScratchKey(); |
void makeBudgeted(); |
void makeUnbudgeted(); |
@@ -304,7 +324,7 @@ private: |
SkAutoTUnref<const SkData> fData; |
typedef GrIORef<GrGpuResource> INHERITED; |
- friend class GrIORef<GrGpuResource>; // to access notifyIsPurgeable. |
+ friend class GrIORef<GrGpuResource>; // to access notifyAllCntsAreZero and notifyRefCntIsZero. |
}; |
#endif |