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 // A lock that can be acquired multiple times on the same thread. 8 9 #ifndef mozilla_RecursiveMutex_h 10 #define mozilla_RecursiveMutex_h 11 12 #include "mozilla/BlockingResourceBase.h" 13 14 #ifndef XP_WIN 15 # include <pthread.h> 16 #endif 17 18 namespace mozilla { 19 20 class RecursiveMutex : public BlockingResourceBase { 21 public: 22 explicit RecursiveMutex(const char* aName); 23 ~RecursiveMutex(); 24 25 #ifdef DEBUG 26 void Lock(); 27 void Unlock(); 28 #else Lock()29 void Lock() { LockInternal(); } Unlock()30 void Unlock() { UnlockInternal(); } 31 #endif 32 33 #ifdef DEBUG 34 /** 35 * AssertCurrentThreadIn 36 **/ 37 void AssertCurrentThreadIn(); 38 /** 39 * AssertNotCurrentThreadIn 40 **/ AssertNotCurrentThreadIn()41 void AssertNotCurrentThreadIn() { 42 // Not currently implemented. See bug 476536 for discussion. 43 } 44 #else AssertCurrentThreadIn()45 void AssertCurrentThreadIn() {} AssertNotCurrentThreadIn()46 void AssertNotCurrentThreadIn() {} 47 #endif 48 49 private: 50 RecursiveMutex() = delete; 51 RecursiveMutex(const RecursiveMutex&) = delete; 52 RecursiveMutex& operator=(const RecursiveMutex&) = delete; 53 54 void LockInternal(); 55 void UnlockInternal(); 56 57 #ifdef DEBUG 58 PRThread* mOwningThread; 59 size_t mEntryCount; 60 #endif 61 62 #if !defined(XP_WIN) 63 pthread_mutex_t mMutex; 64 #else 65 // We eschew including windows.h and using CRITICAL_SECTION here so that files 66 // including us don't also pull in windows.h. Just use a type that's big 67 // enough for CRITICAL_SECTION, and we'll fix it up later. 68 void* mMutex[6]; 69 #endif 70 }; 71 72 class MOZ_RAII RecursiveMutexAutoLock { 73 public: RecursiveMutexAutoLock(RecursiveMutex & aRecursiveMutex)74 explicit RecursiveMutexAutoLock(RecursiveMutex& aRecursiveMutex) 75 : mRecursiveMutex(&aRecursiveMutex) { 76 NS_ASSERTION(mRecursiveMutex, "null mutex"); 77 mRecursiveMutex->Lock(); 78 } 79 ~RecursiveMutexAutoLock(void)80 ~RecursiveMutexAutoLock(void) { mRecursiveMutex->Unlock(); } 81 82 private: 83 RecursiveMutexAutoLock() = delete; 84 RecursiveMutexAutoLock(const RecursiveMutexAutoLock&) = delete; 85 RecursiveMutexAutoLock& operator=(const RecursiveMutexAutoLock&) = delete; 86 static void* operator new(size_t) noexcept(true); 87 88 mozilla::RecursiveMutex* mRecursiveMutex; 89 }; 90 91 class MOZ_RAII RecursiveMutexAutoUnlock { 92 public: RecursiveMutexAutoUnlock(RecursiveMutex & aRecursiveMutex)93 explicit RecursiveMutexAutoUnlock(RecursiveMutex& aRecursiveMutex) 94 : mRecursiveMutex(&aRecursiveMutex) { 95 NS_ASSERTION(mRecursiveMutex, "null mutex"); 96 mRecursiveMutex->Unlock(); 97 } 98 ~RecursiveMutexAutoUnlock(void)99 ~RecursiveMutexAutoUnlock(void) { mRecursiveMutex->Lock(); } 100 101 private: 102 RecursiveMutexAutoUnlock() = delete; 103 RecursiveMutexAutoUnlock(const RecursiveMutexAutoUnlock&) = delete; 104 RecursiveMutexAutoUnlock& operator=(const RecursiveMutexAutoUnlock&) = delete; 105 static void* operator new(size_t) noexcept(true); 106 107 mozilla::RecursiveMutex* mRecursiveMutex; 108 }; 109 110 } // namespace mozilla 111 112 #endif // mozilla_RecursiveMutex_h 113