Mutex.h (2447B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef threading_Mutex_h 8 #define threading_Mutex_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/PlatformMutex.h" 12 #include "mozilla/ThreadLocal.h" 13 14 #include "threading/ThreadId.h" 15 16 namespace js { 17 18 // A MutexId secifies the name and mutex order for a mutex. 19 // 20 // The mutex order defines the allowed order of mutex acqusition on a single 21 // thread. Mutexes must be acquired in strictly increasing order. Mutexes with 22 // the same order may not be held at the same time by that thread. 23 struct MutexId { 24 const char* name; 25 uint32_t order; 26 }; 27 28 // The Mutex class below wraps mozilla::detail::MutexImpl, but we don't want to 29 // use public inheritance, and private inheritance is problematic because 30 // Mutex's friends can access the private parent class as if it was public 31 // inheritance. So use a data member, but for Mutex to access the data member 32 // we must override it and make Mutex a friend. 33 class MutexImpl : public mozilla::detail::MutexImpl { 34 protected: 35 MutexImpl() {} 36 37 friend class Mutex; 38 }; 39 40 // In debug builds, js::Mutex is a wrapper over MutexImpl that checks correct 41 // locking order is observed. 42 // 43 // The class maintains a per-thread stack of currently-held mutexes to enable it 44 // to check this. 45 class Mutex { 46 private: 47 MutexImpl impl_; 48 49 #ifdef DEBUG 50 const MutexId id_; 51 Mutex* prev_ = nullptr; 52 ThreadId owningThread_; 53 54 static MOZ_THREAD_LOCAL(Mutex*) HeldMutexStack; 55 #endif 56 57 public: 58 #ifdef DEBUG 59 static bool Init(); 60 61 explicit Mutex(const MutexId& id) : id_(id) { MOZ_ASSERT(id_.order != 0); } 62 63 void lock(); 64 bool tryLock(); 65 void unlock(); 66 bool isOwnedByCurrentThread() const; 67 void assertOwnedByCurrentThread() const; 68 #else 69 static bool Init() { return true; } 70 71 explicit Mutex(const MutexId& id) {} 72 73 void lock() { impl_.lock(); } 74 bool tryLock() { return impl_.tryLock(); } 75 void unlock() { impl_.unlock(); } 76 void assertOwnedByCurrentThread() const {}; 77 #endif 78 79 private: 80 #ifdef DEBUG 81 void preLockChecks() const; 82 void postLockChecks(); 83 void preUnlockChecks(); 84 #endif 85 86 friend class ConditionVariable; 87 }; 88 89 } // namespace js 90 91 #endif // threading_Mutex_h