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/. */
7 // A lock that can be acquired multiple times on the same thread.
9 #ifndef mozilla_RecursiveMutex_h
10 #define mozilla_RecursiveMutex_h
12 #include "mozilla/ThreadSafety.h"
13 #include "mozilla/BlockingResourceBase.h"
21 class MOZ_CAPABILITY("recursive mutex") RecursiveMutex
22 : public BlockingResourceBase
{
24 explicit RecursiveMutex(const char* aName
);
28 void Lock() MOZ_CAPABILITY_ACQUIRE();
29 void Unlock() MOZ_CAPABILITY_RELEASE();
31 void Lock() MOZ_CAPABILITY_ACQUIRE() { LockInternal(); }
32 void Unlock() MOZ_CAPABILITY_RELEASE() { UnlockInternal(); }
37 * AssertCurrentThreadIn
39 void AssertCurrentThreadIn() const MOZ_ASSERT_CAPABILITY(this);
41 * AssertNotCurrentThreadIn
43 void AssertNotCurrentThreadIn() const MOZ_EXCLUDES(this) {
44 // Not currently implemented. See bug 476536 for discussion.
47 void AssertCurrentThreadIn() const MOZ_ASSERT_CAPABILITY(this) {}
48 void AssertNotCurrentThreadIn() const MOZ_EXCLUDES(this) {}
52 RecursiveMutex() = delete;
53 RecursiveMutex(const RecursiveMutex
&) = delete;
54 RecursiveMutex
& operator=(const RecursiveMutex
&) = delete;
57 void UnlockInternal();
60 PRThread
* mOwningThread
;
65 pthread_mutex_t mMutex
;
67 // We eschew including windows.h and using CRITICAL_SECTION here so that files
68 // including us don't also pull in windows.h. Just use a type that's big
69 // enough for CRITICAL_SECTION, and we'll fix it up later.
74 class MOZ_RAII MOZ_SCOPED_CAPABILITY RecursiveMutexAutoLock
{
76 explicit RecursiveMutexAutoLock(RecursiveMutex
& aRecursiveMutex
)
77 MOZ_CAPABILITY_ACQUIRE(aRecursiveMutex
)
78 : mRecursiveMutex(&aRecursiveMutex
) {
79 NS_ASSERTION(mRecursiveMutex
, "null mutex");
80 mRecursiveMutex
->Lock();
83 ~RecursiveMutexAutoLock(void) MOZ_CAPABILITY_RELEASE() {
84 mRecursiveMutex
->Unlock();
88 RecursiveMutexAutoLock() = delete;
89 RecursiveMutexAutoLock(const RecursiveMutexAutoLock
&) = delete;
90 RecursiveMutexAutoLock
& operator=(const RecursiveMutexAutoLock
&) = delete;
91 static void* operator new(size_t) noexcept(true);
93 mozilla::RecursiveMutex
* mRecursiveMutex
;
96 class MOZ_RAII MOZ_SCOPED_CAPABILITY RecursiveMutexAutoUnlock
{
98 explicit RecursiveMutexAutoUnlock(RecursiveMutex
& aRecursiveMutex
)
99 MOZ_SCOPED_UNLOCK_RELEASE(aRecursiveMutex
)
100 : mRecursiveMutex(&aRecursiveMutex
) {
101 NS_ASSERTION(mRecursiveMutex
, "null mutex");
102 mRecursiveMutex
->Unlock();
105 ~RecursiveMutexAutoUnlock(void) MOZ_SCOPED_UNLOCK_REACQUIRE() {
106 mRecursiveMutex
->Lock();
110 RecursiveMutexAutoUnlock() = delete;
111 RecursiveMutexAutoUnlock(const RecursiveMutexAutoUnlock
&) = delete;
112 RecursiveMutexAutoUnlock
& operator=(const RecursiveMutexAutoUnlock
&) = delete;
113 static void* operator new(size_t) noexcept(true);
115 mozilla::RecursiveMutex
* mRecursiveMutex
;
118 } // namespace mozilla
120 #endif // mozilla_RecursiveMutex_h