1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkMutex_DEFINED 9 #define SkMutex_DEFINED 10 11 #include "../private/SkSemaphore.h" 12 #include "../private/SkThreadID.h" 13 #include "SkTypes.h" 14 15 #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name; 16 17 class SkBaseMutex { 18 public: 19 constexpr SkBaseMutex() = default; 20 acquire()21 void acquire() { 22 fSemaphore.wait(); 23 SkDEBUGCODE(fOwner = SkGetThreadID();) 24 } 25 release()26 void release() { 27 this->assertHeld(); 28 SkDEBUGCODE(fOwner = kIllegalThreadID;) 29 fSemaphore.signal(); 30 } 31 assertHeld()32 void assertHeld() { 33 SkASSERT(fOwner == SkGetThreadID()); 34 } 35 36 protected: 37 SkBaseSemaphore fSemaphore{1}; 38 SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};) 39 }; 40 41 class SkMutex : public SkBaseMutex { 42 public: 43 using SkBaseMutex::SkBaseMutex; ~SkMutex()44 ~SkMutex() { fSemaphore.cleanup(); } 45 }; 46 47 class SkAutoMutexAcquire { 48 public: 49 template <typename T> SkAutoMutexAcquire(T * mutex)50 SkAutoMutexAcquire(T* mutex) : fMutex(mutex) { 51 if (mutex) { 52 mutex->acquire(); 53 } 54 fRelease = [](void* mutex) { ((T*)mutex)->release(); }; 55 } 56 57 template <typename T> SkAutoMutexAcquire(T & mutex)58 SkAutoMutexAcquire(T& mutex) : SkAutoMutexAcquire(&mutex) {} 59 ~SkAutoMutexAcquire()60 ~SkAutoMutexAcquire() { this->release(); } 61 release()62 void release() { 63 if (fMutex) { 64 fRelease(fMutex); 65 } 66 fMutex = nullptr; 67 } 68 69 private: 70 void* fMutex; 71 void (*fRelease)(void*); 72 }; 73 #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire) 74 75 // SkAutoExclusive is a lighter weight version of SkAutoMutexAcquire. 76 // It assumes that there is a valid mutex, obviating the null check. 77 class SkAutoExclusive { 78 public: 79 template <typename T> SkAutoExclusive(T & mutex)80 SkAutoExclusive(T& mutex) : fMutex(&mutex) { 81 mutex.acquire(); 82 83 fRelease = [](void* mutex) { ((T*)mutex)->release(); }; 84 } ~SkAutoExclusive()85 ~SkAutoExclusive() { fRelease(fMutex); } 86 87 private: 88 void* fMutex; 89 void (*fRelease)(void*); 90 }; 91 #define SkAutoExclusive(...) SK_REQUIRE_LOCAL_VAR(SkAutoExclusive) 92 93 #endif//SkMutex_DEFINED 94