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 #ifndef mozilla_glue_MozglueUtils_h
8 #define mozilla_glue_MozglueUtils_h
12 #include "mozilla/Atomics.h"
13 #include "mozilla/Attributes.h"
20 class MOZ_STATIC_CLASS Win32SRWLock final
{
22 // Microsoft guarantees that '0' is never a valid thread id
23 // https://docs.microsoft.com/en-ca/windows/desktop/ProcThread/thread-handles-and-identifiers
24 static const DWORD kInvalidThreadId
= 0;
26 constexpr Win32SRWLock()
27 : mExclusiveThreadId(kInvalidThreadId
), mLock(SRWLOCK_INIT
) {}
29 ~Win32SRWLock() { MOZ_ASSERT(mExclusiveThreadId
== kInvalidThreadId
); }
33 mExclusiveThreadId
!= GetCurrentThreadId(),
34 "Deadlock detected - A thread attempted to acquire a shared lock on "
35 "a SRWLOCK when it already owns the exclusive lock on it.");
37 ::AcquireSRWLockShared(&mLock
);
40 void UnlockShared() { ::ReleaseSRWLockShared(&mLock
); }
42 void LockExclusive() {
44 mExclusiveThreadId
!= GetCurrentThreadId(),
45 "Deadlock detected - A thread attempted to acquire an exclusive lock "
46 "on a SRWLOCK when it already owns the exclusive lock on it.");
48 ::AcquireSRWLockExclusive(&mLock
);
49 mExclusiveThreadId
= GetCurrentThreadId();
52 void UnlockExclusive() {
53 MOZ_ASSERT(mExclusiveThreadId
== GetCurrentThreadId());
55 mExclusiveThreadId
= kInvalidThreadId
;
56 ::ReleaseSRWLockExclusive(&mLock
);
59 Win32SRWLock(const Win32SRWLock
&) = delete;
60 Win32SRWLock(Win32SRWLock
&&) = delete;
61 Win32SRWLock
& operator=(const Win32SRWLock
&) = delete;
62 Win32SRWLock
& operator=(Win32SRWLock
&&) = delete;
65 // "Relaxed" memory ordering is fine. Threads will see other thread IDs
66 // appear here in some non-deterministic ordering (or not at all) and simply
69 // But a thread will only read its own ID if it previously wrote it, and a
70 // single thread doesn't need a memory barrier to read its own write.
72 Atomic
<DWORD
, Relaxed
> mExclusiveThreadId
;
78 class MOZ_STATIC_CLASS Win32SRWLock final
{
80 constexpr Win32SRWLock() : mLock(SRWLOCK_INIT
) {}
82 void LockShared() { ::AcquireSRWLockShared(&mLock
); }
84 void UnlockShared() { ::ReleaseSRWLockShared(&mLock
); }
86 void LockExclusive() { ::AcquireSRWLockExclusive(&mLock
); }
88 void UnlockExclusive() { ::ReleaseSRWLockExclusive(&mLock
); }
90 ~Win32SRWLock() = default;
92 Win32SRWLock(const Win32SRWLock
&) = delete;
93 Win32SRWLock(Win32SRWLock
&&) = delete;
94 Win32SRWLock
& operator=(const Win32SRWLock
&) = delete;
95 Win32SRWLock
& operator=(Win32SRWLock
&&) = delete;
103 class MOZ_RAII AutoSharedLock final
{
105 explicit AutoSharedLock(Win32SRWLock
& aLock
) : mLock(aLock
) {
109 ~AutoSharedLock() { mLock
.UnlockShared(); }
111 AutoSharedLock(const AutoSharedLock
&) = delete;
112 AutoSharedLock(AutoSharedLock
&&) = delete;
113 AutoSharedLock
& operator=(const AutoSharedLock
&) = delete;
114 AutoSharedLock
& operator=(AutoSharedLock
&&) = delete;
120 class MOZ_RAII AutoExclusiveLock final
{
122 explicit AutoExclusiveLock(Win32SRWLock
& aLock
) : mLock(aLock
) {
123 mLock
.LockExclusive();
126 ~AutoExclusiveLock() { mLock
.UnlockExclusive(); }
128 AutoExclusiveLock(const AutoExclusiveLock
&) = delete;
129 AutoExclusiveLock(AutoExclusiveLock
&&) = delete;
130 AutoExclusiveLock
& operator=(const AutoExclusiveLock
&) = delete;
131 AutoExclusiveLock
& operator=(AutoExclusiveLock
&&) = delete;
138 } // namespace mozilla
140 #endif // mozilla_glue_MozglueUtils_h