Index: src/core/SkSharedMutex.h |
diff --git a/src/core/SkSharedMutex.h b/src/core/SkSharedMutex.h |
index f3430040e38b51ee05ddb9d2915db44a30ff6ec3..358f4960a7a38fad00850cca16bba36e4b6f6700 100644 |
--- a/src/core/SkSharedMutex.h |
+++ b/src/core/SkSharedMutex.h |
@@ -11,9 +11,25 @@ |
#include "SkAtomics.h" |
#include "SkSemaphore.h" |
#include "SkTypes.h" |
- |
-// This is a shared lock implementation similar to pthreads rwlocks. This implementation is |
-// cribbed from Preshing's article: |
+ |
+#ifdef SK_DEBUG |
+ #include "SkMutex.h" |
+ #include "SkTDArray.h" |
+ #ifdef SK_BUILD_FOR_WIN |
+ #include <windows.h> |
+ typedef DWORD threadID_t; |
+ static threadID_t getThreadID() { return GetCurrentThreadId(); } |
mtklein_C
2015/09/17 19:51:42
These standalone statics are typically get_thread_
herb_g
2015/09/17 21:39:41
Done.
|
+ #else |
+ #include <pthread.h> |
+ typedef pthread_t threadID_t; |
+ static threadID_t getThreadID() { return pthread_self(); } |
mtklein_C
2015/09/17 19:51:42
static int64_t get_thread_id() { return (int64_t)p
herb_g
2015/09/17 21:39:41
Done.
|
+ #endif |
+#endif // SK_DEBUG |
+ |
+// There are two shared lock implementations one debug the other is high performance. They implement |
+// an interface similar to pthread's rwlocks. |
+// This is a shared lock implementation similar to pthreads rwlocks. The high performance |
+// implementation is cribbed from Preshing's article: |
// http://preshing.com/20150316/semaphores-are-surprisingly-versatile/ |
// |
// This lock does not obey strict queue ordering. It will always alternate between readers and |
@@ -29,11 +45,7 @@ public: |
void release(); |
// Fail if exclusive is not held. |
-#ifdef SK_DEBUG |
void assertHeld() const; |
mtklein_C
2015/09/17 19:51:42
undo these bits?
herb_g
2015/09/17 21:39:41
Done.
|
-#else |
- void assertHeld() const {} |
-#endif |
// Acquire lock for shared use. |
void acquireShared(); |
@@ -42,17 +54,72 @@ public: |
void releaseShared(); |
// Fail if shared lock not held. |
-#ifdef SK_DEBUG |
void assertHeldShared() const; |
-#else |
- void assertHeldShared() const {} |
-#endif |
private: |
+#ifdef SK_DEBUG |
+ class ThreadID { |
+ public: |
+ ThreadID() : fThreadID(getThreadID()) { } |
+ bool operator==(const ThreadID& that) const { return fThreadID == that.fThreadID; } |
+ int64_t toInt() const { return (int64_t)fThreadID; } |
+ private: |
+ threadID_t fThreadID; |
+ }; |
+ |
+ class ThreadIDSet { |
+ public: |
+ // Returns true if threadID is in the set. |
+ bool find(ThreadID threadID) const { |
+ for (auto& t : fThreadIDs) { |
+ if (t == threadID) return true; |
+ } |
+ return false; |
+ } |
+ |
+ // Returns true if did not already exist. |
+ bool tryAdd(ThreadID threadID) { |
+ for (auto& t : fThreadIDs) { |
+ if (t == threadID) return false; |
+ } |
+ fThreadIDs.append(1, &threadID); |
+ return true; |
+ } |
+ // Returns true if already exists in Set. |
+ bool tryRemove(ThreadID threadID) { |
+ for (int i = 0; i < fThreadIDs.count(); ++i) { |
+ if (fThreadIDs[i] == threadID) { |
+ fThreadIDs.remove(i); |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ void swap(ThreadIDSet& other) { |
+ fThreadIDs.swap(other.fThreadIDs); |
+ } |
+ |
+ int count() const { |
+ return fThreadIDs.count(); |
+ } |
+ |
+ private: |
+ SkTDArray<ThreadID> fThreadIDs; |
+ }; |
+ |
+ ThreadIDSet fCurrentShared; |
+ ThreadIDSet fWaitingExclusive; |
+ ThreadIDSet fWaitingShared; |
+ int fSharedQueueSelect{0}; |
+ mutable SkMutex fMu; |
+ SkSemaphore fSharedQueue[2]; |
+ SkSemaphore fExclusiveQueue; |
+#else |
SkAtomic<int32_t> fQueueCounts; |
- SkSemaphore fSharedQueue; |
- SkSemaphore fExclusiveQueue; |
+ SkSemaphore fSharedQueue; |
+ SkSemaphore fExclusiveQueue; |
+#endif // SK_DEBUG |
}; |
- |
#endif // SkSharedLock_DEFINED |