WeakRefCnt
http://codereview.appspot.com/5649046/
git-svn-id: http://skia.googlecode.com/svn/trunk@3978 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkTypefaceCache.cpp b/src/core/SkTypefaceCache.cpp
index f4397a6..ee5ced9 100644
--- a/src/core/SkTypefaceCache.cpp
+++ b/src/core/SkTypefaceCache.cpp
@@ -13,7 +13,9 @@
#define TYPEFACE_CACHE_LIMIT 128
-void SkTypefaceCache::add(SkTypeface* face, SkTypeface::Style requestedStyle) {
+void SkTypefaceCache::add(SkTypeface* face,
+ SkTypeface::Style requestedStyle,
+ bool strong) {
if (fArray.count() >= TYPEFACE_CACHE_LIMIT) {
this->purge(TYPEFACE_CACHE_LIMIT >> 2);
}
@@ -21,7 +23,12 @@
Rec* rec = fArray.append();
rec->fFace = face;
rec->fRequestedStyle = requestedStyle;
- face->ref();
+ rec->fStrong = strong;
+ if (strong) {
+ face->ref();
+ } else {
+ face->weak_ref();
+ }
}
SkTypeface* SkTypefaceCache::findByID(SkFontID fontID) const {
@@ -36,12 +43,20 @@
return NULL;
}
-SkTypeface* SkTypefaceCache::findByProc(FindProc proc, void* ctx) const {
+SkTypeface* SkTypefaceCache::findByProcAndRef(FindProc proc, void* ctx) const {
const Rec* curr = fArray.begin();
const Rec* stop = fArray.end();
while (curr < stop) {
- if (proc(curr->fFace, curr->fRequestedStyle, ctx)) {
- return curr->fFace;
+ SkTypeface* currFace = curr->fFace;
+ if (proc(currFace, curr->fRequestedStyle, ctx)) {
+ if (curr->fStrong) {
+ currFace->ref();
+ return currFace;
+ } else if (currFace->try_ref()) {
+ return currFace;
+ } else {
+ //remove currFace from fArray?
+ }
}
curr += 1;
}
@@ -53,8 +68,15 @@
int i = 0;
while (i < count) {
SkTypeface* face = fArray[i].fFace;
- if (1 == face->getRefCnt()) {
- face->unref();
+ bool strong = fArray[i].fStrong;
+ if ((strong && face->getRefCnt() == 1) ||
+ (!strong && face->weak_expired()))
+ {
+ if (strong) {
+ face->unref();
+ } else {
+ face->weak_unref();
+ }
fArray.remove(i);
--count;
if (--numToPurge == 0) {
@@ -84,9 +106,11 @@
SK_DECLARE_STATIC_MUTEX(gMutex);
-void SkTypefaceCache::Add(SkTypeface* face, SkTypeface::Style requestedStyle) {
+void SkTypefaceCache::Add(SkTypeface* face,
+ SkTypeface::Style requestedStyle,
+ bool strong) {
SkAutoMutexAcquire ama(gMutex);
- Get().add(face, requestedStyle);
+ Get().add(face, requestedStyle, strong);
}
SkTypeface* SkTypefaceCache::FindByID(SkFontID fontID) {
@@ -96,8 +120,7 @@
SkTypeface* SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
SkAutoMutexAcquire ama(gMutex);
- SkTypeface* typeface = Get().findByProc(proc, ctx);
- SkSafeRef(typeface);
+ SkTypeface* typeface = Get().findByProcAndRef(proc, ctx);
return typeface;
}
@@ -119,7 +142,7 @@
void SkTypefaceCache::Dump() {
#ifdef SK_DEBUG
SkAutoMutexAcquire ama(gMutex);
- (void)Get().findByProc(DumpProc, NULL);
+ (void)Get().findByProcAndRef(DumpProc, NULL);
#endif
}
diff --git a/src/core/SkTypefaceCache.h b/src/core/SkTypefaceCache.h
index e65ec90..b6cab81 100644
--- a/src/core/SkTypefaceCache.h
+++ b/src/core/SkTypefaceCache.h
@@ -26,7 +26,7 @@
/**
* Callback for FindByProc. Returns true if the given typeface is a match
* for the given context. The passed typeface is owned by the cache and is
- * not additionally ref()ed.
+ * not additionally ref()ed. The typeface may be in the disposed state.
*/
typedef bool (*FindProc)(SkTypeface*, SkTypeface::Style, void* context);
@@ -42,7 +42,9 @@
* whose refcnt is 1 (meaning only the cache is an owner) will be
* unref()ed.
*/
- static void Add(SkTypeface*, SkTypeface::Style requested);
+ static void Add(SkTypeface*,
+ SkTypeface::Style requested,
+ bool strong = true);
/**
* Search the cache for a typeface with the specified fontID (uniqueID).
@@ -75,14 +77,15 @@
private:
static SkTypefaceCache& Get();
- void add(SkTypeface*, SkTypeface::Style requested);
+ void add(SkTypeface*, SkTypeface::Style requested, bool strong = true);
SkTypeface* findByID(SkFontID findID) const;
- SkTypeface* findByProc(FindProc proc, void* ctx) const;
+ SkTypeface* findByProcAndRef(FindProc proc, void* ctx) const;
void purge(int count);
void purgeAll();
struct Rec {
SkTypeface* fFace;
+ bool fStrong;
SkTypeface::Style fRequestedStyle;
};
SkTDArray<Rec> fArray;
diff --git a/src/ports/SkThread_none.cpp b/src/ports/SkThread_none.cpp
index a948a54..56bbbae 100644
--- a/src/ports/SkThread_none.cpp
+++ b/src/ports/SkThread_none.cpp
@@ -21,6 +21,14 @@
*addr = value - 1;
return value;
}
+void sk_membar_aquire__after_atomic_dec() { }
+
+int32_t sk_atomic_conditional_inc(int32_t* addr) {
+ int32_t value = *addr;
+ if (value != 0) ++*addr;
+ return value;
+}
+void sk_membar_aquire__after_atomic_conditional_inc() { }
SkMutex::SkMutex() {}
diff --git a/src/ports/SkThread_pthread.cpp b/src/ports/SkThread_pthread.cpp
index 6a4fade..d0bb3ac 100644
--- a/src/ports/SkThread_pthread.cpp
+++ b/src/ports/SkThread_pthread.cpp
@@ -39,6 +39,27 @@
{
return __sync_fetch_and_add(addr, -1);
}
+void sk_membar_aquire__after_atomic_dec() { }
+
+int32_t sk_atomic_conditional_inc(int32_t* addr)
+{
+ int32_t value = *addr;
+
+ while (true) {
+ if (value == 0) {
+ return 0;
+ }
+
+ int32_t before = __sync_val_compare_and_swap(addr, value, value + 1);
+
+ if (before == value) {
+ return value;
+ } else {
+ value = before;
+ }
+ }
+}
+void sk_membar_aquire__after_atomic_conditional_inc() { }
#else
@@ -61,6 +82,17 @@
*addr = value - 1;
return value;
}
+void sk_membar_aquire__after_atomic_dec() { }
+
+int32_t sk_atomic_conditional_inc(int32_t* addr)
+{
+ SkAutoMutexAcquire ac(gAtomicMutex);
+
+ int32_t value = *addr;
+ if (value != 0) ++*addr;
+ return value;
+}
+void sk_membar_aquire__after_atomic_conditional_inc() { }
#endif
diff --git a/src/ports/SkThread_win.cpp b/src/ports/SkThread_win.cpp
index 6c960e2..e833314 100644
--- a/src/ports/SkThread_win.cpp
+++ b/src/ports/SkThread_win.cpp
@@ -17,6 +17,7 @@
//directive.
//The pragma appears to be unnecessary, but doesn't hurt.
#pragma intrinsic(_InterlockedIncrement, _InterlockedDecrement)
+#pragma intrinsic(_InterlockedCompareExchange)
int32_t sk_atomic_inc(int32_t* addr) {
// InterlockedIncrement returns the new value, we want to return the old.
@@ -26,6 +27,22 @@
int32_t sk_atomic_dec(int32_t* addr) {
return _InterlockedDecrement(reinterpret_cast<LONG*>(addr)) + 1;
}
+void sk_membar_aquire__after_atomic_dec() { }
+
+int32_t sk_atomic_conditional_inc(int32_t* addr) {
+ while (true) {
+ LONG value = static_cast<LONG const volatile&>(*addr);
+ if (value == 0) {
+ return 0;
+ }
+ if (_InterlockedCompareExchange(reinterpret_cast<LONG*>(addr),
+ value + 1,
+ value) == value) {
+ return value;
+ }
+ }
+}
+void sk_membar_aquire__after_atomic_conditional_inc() { }
SkMutex::SkMutex() {
SK_COMPILE_ASSERT(sizeof(fStorage) > sizeof(CRITICAL_SECTION),