aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core
diff options
context:
space:
mode:
authorGravatar herb <herb@google.com>2015-09-24 07:34:49 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-09-24 07:34:49 -0700
commit7f0a3d7523377097184309152f883f1fcb12a4b8 (patch)
treeb7f6d9ee1208ead229a40240d26d765dd446c2ae /include/core
parentc6363ef7b4763b36a9a0d255bc775a973d2fc7a5 (diff)
Make mutex semaphore based.
This implementation improves performance of SkMutex acquire / release pair from 42ns -> 13 ns. SkSharedMutex and SkSpinlock have the same performance. It also removes specialized windows and linux/mac code. BUG=skia: Review URL: https://codereview.chromium.org/1359733002
Diffstat (limited to 'include/core')
-rw-r--r--include/core/SkMutex.h70
1 files changed, 63 insertions, 7 deletions
diff --git a/include/core/SkMutex.h b/include/core/SkMutex.h
index eb5e29b80a..77a00f0235 100644
--- a/include/core/SkMutex.h
+++ b/include/core/SkMutex.h
@@ -9,15 +9,73 @@
#define SkMutex_DEFINED
// This file is not part of the public Skia API.
+#include "../private/SkSemaphore.h"
#include "SkTypes.h"
-// IWYU pragma: begin_exports
-#if defined(SK_BUILD_FOR_WIN)
- #include "../ports/SkMutex_win.h"
+#define SK_MUTEX_SEMAPHORE_INIT {1, {0}}
+
+#ifdef SK_DEBUG
+ #define SK_BASE_MUTEX_INIT {SK_MUTEX_SEMAPHORE_INIT, 0}
#else
- #include "../ports/SkMutex_pthread.h"
+ #define SK_BASE_MUTEX_INIT {SK_MUTEX_SEMAPHORE_INIT}
+#endif
+
+// Using POD-style initialization prevents the generation of a static initializer.
+//
+// Without magic statics there are no thread safety guarantees on initialization
+// of local statics (even POD). As a result, it is illegal to use
+// SK_DECLARE_STATIC_MUTEX in a function.
+//
+// Because SkBaseMutex is not a primitive, a static SkBaseMutex cannot be
+// initialized in a class with this macro.
+#define SK_DECLARE_STATIC_MUTEX(name) namespace {} static SkBaseMutex name = SK_BASE_MUTEX_INIT;
+
+// TODO(herb): unify this with the ThreadID in SkSharedMutex.cpp.
+#ifdef SK_DEBUG
+ #ifdef SK_BUILD_FOR_WIN
+ #include <windows.h>
+ inline int64_t sk_get_thread_id() { return GetCurrentThreadId(); }
+ #else
+ #include <pthread.h>
+ inline int64_t sk_get_thread_id() { return (int64_t)pthread_self(); }
+ #endif
#endif
-// IWYU pragma: end_exports
+
+typedef int64_t SkThreadID;
+
+SkDEBUGCODE(static const SkThreadID kNoOwner = 0;)
+
+struct SkBaseMutex {
+ void acquire() {
+ fSemaphore.wait();
+ SkDEBUGCODE(fOwner = sk_get_thread_id();)
+ }
+
+ void release() {
+ this->assertHeld();
+ SkDEBUGCODE(fOwner = kNoOwner;)
+ fSemaphore.signal();
+ }
+
+ void assertHeld() {
+ SkASSERT(fOwner == sk_get_thread_id());
+ }
+
+ SkBaseSemaphore fSemaphore;
+ SkDEBUGCODE(SkThreadID fOwner;)
+};
+
+// This needs to use subclassing instead of encapsulation to make SkAutoMutexAcquire to work.
+class SkMutex : public SkBaseMutex {
+public:
+ SkMutex () {
+ fSemaphore = SK_MUTEX_SEMAPHORE_INIT;
+ SkDEBUGCODE(fOwner = kNoOwner);
+ }
+ ~SkMutex () { fSemaphore.deleteSemaphore(); }
+ SkMutex(const SkMutex&) = delete;
+ SkMutex& operator=(const SkMutex&) = delete;
+};
template <typename Lock>
class SkAutoTAcquire : SkNoncopyable {
@@ -59,8 +117,6 @@ private:
};
typedef SkAutoTAcquire<SkBaseMutex> SkAutoMutexAcquire;
-
#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
-
#endif//SkMutex_DEFINED