diff options
author | 2015-09-24 07:34:49 -0700 | |
---|---|---|
committer | 2015-09-24 07:34:49 -0700 | |
commit | 7f0a3d7523377097184309152f883f1fcb12a4b8 (patch) | |
tree | b7f6d9ee1208ead229a40240d26d765dd446c2ae /include/core | |
parent | c6363ef7b4763b36a9a0d255bc775a973d2fc7a5 (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.h | 70 |
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 |