From 62a69c26b3a34c259918d6c97b4dea76b6285b67 Mon Sep 17 00:00:00 2001 From: herb Date: Tue, 29 Sep 2015 11:47:45 -0700 Subject: Move Mutexy things to private. There is no API change. TBR=reed@google.com BUG=skia: Review URL: https://codereview.chromium.org/1368333004 --- include/private/SkMutex.h | 122 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 include/private/SkMutex.h (limited to 'include/private/SkMutex.h') diff --git a/include/private/SkMutex.h b/include/private/SkMutex.h new file mode 100644 index 0000000000..77a00f0235 --- /dev/null +++ b/include/private/SkMutex.h @@ -0,0 +1,122 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkMutex_DEFINED +#define SkMutex_DEFINED + +// This file is not part of the public Skia API. +#include "../private/SkSemaphore.h" +#include "SkTypes.h" + +#define SK_MUTEX_SEMAPHORE_INIT {1, {0}} + +#ifdef SK_DEBUG + #define SK_BASE_MUTEX_INIT {SK_MUTEX_SEMAPHORE_INIT, 0} +#else + #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 + inline int64_t sk_get_thread_id() { return GetCurrentThreadId(); } + #else + #include + inline int64_t sk_get_thread_id() { return (int64_t)pthread_self(); } + #endif +#endif + +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 +class SkAutoTAcquire : SkNoncopyable { +public: + explicit SkAutoTAcquire(Lock& mutex) : fMutex(&mutex) { + SkASSERT(fMutex != NULL); + mutex.acquire(); + } + + explicit SkAutoTAcquire(Lock* mutex) : fMutex(mutex) { + if (mutex) { + mutex->acquire(); + } + } + + /** If the mutex has not been released, release it now. */ + ~SkAutoTAcquire() { + if (fMutex) { + fMutex->release(); + } + } + + /** If the mutex has not been released, release it now. */ + void release() { + if (fMutex) { + fMutex->release(); + fMutex = NULL; + } + } + + /** Assert that we're holding the mutex. */ + void assertHeld() { + SkASSERT(fMutex); + fMutex->assertHeld(); + } + +private: + Lock* fMutex; +}; + +typedef SkAutoTAcquire SkAutoMutexAcquire; +#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire) + +#endif//SkMutex_DEFINED -- cgit v1.2.3