WinUtils.h (4043B)
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 mozilla_glue_MozglueUtils_h 8 #define mozilla_glue_MozglueUtils_h 9 10 #include <windows.h> 11 12 #include "mozilla/Atomics.h" 13 #include "mozilla/Attributes.h" 14 15 namespace mozilla { 16 namespace glue { 17 18 #ifdef DEBUG 19 20 class MOZ_STATIC_CLASS Win32SRWLock final { 21 public: 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; 25 26 constexpr Win32SRWLock() 27 : mExclusiveThreadId(kInvalidThreadId), mLock(SRWLOCK_INIT) {} 28 29 ~Win32SRWLock() { MOZ_ASSERT(mExclusiveThreadId == kInvalidThreadId); } 30 31 void LockShared() { 32 MOZ_ASSERT( 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."); 36 37 ::AcquireSRWLockShared(&mLock); 38 } 39 40 void UnlockShared() { ::ReleaseSRWLockShared(&mLock); } 41 42 void LockExclusive() { 43 MOZ_ASSERT( 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."); 47 48 ::AcquireSRWLockExclusive(&mLock); 49 mExclusiveThreadId = GetCurrentThreadId(); 50 } 51 52 void UnlockExclusive() { 53 MOZ_ASSERT(mExclusiveThreadId == GetCurrentThreadId()); 54 55 mExclusiveThreadId = kInvalidThreadId; 56 ::ReleaseSRWLockExclusive(&mLock); 57 } 58 59 Win32SRWLock(const Win32SRWLock&) = delete; 60 Win32SRWLock(Win32SRWLock&&) = delete; 61 Win32SRWLock& operator=(const Win32SRWLock&) = delete; 62 Win32SRWLock& operator=(Win32SRWLock&&) = delete; 63 64 private: 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 67 // ignore them. 68 // 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. 71 72 Atomic<DWORD, Relaxed> mExclusiveThreadId; 73 SRWLOCK mLock; 74 }; 75 76 #else // DEBUG 77 78 class MOZ_STATIC_CLASS Win32SRWLock final { 79 public: 80 constexpr Win32SRWLock() : mLock(SRWLOCK_INIT) {} 81 82 void LockShared() { ::AcquireSRWLockShared(&mLock); } 83 84 void UnlockShared() { ::ReleaseSRWLockShared(&mLock); } 85 86 void LockExclusive() { ::AcquireSRWLockExclusive(&mLock); } 87 88 void UnlockExclusive() { ::ReleaseSRWLockExclusive(&mLock); } 89 90 ~Win32SRWLock() = default; 91 92 Win32SRWLock(const Win32SRWLock&) = delete; 93 Win32SRWLock(Win32SRWLock&&) = delete; 94 Win32SRWLock& operator=(const Win32SRWLock&) = delete; 95 Win32SRWLock& operator=(Win32SRWLock&&) = delete; 96 97 private: 98 SRWLOCK mLock; 99 }; 100 101 #endif 102 103 class MOZ_RAII AutoSharedLock final { 104 public: 105 explicit AutoSharedLock(Win32SRWLock& aLock) : mLock(aLock) { 106 mLock.LockShared(); 107 } 108 109 ~AutoSharedLock() { mLock.UnlockShared(); } 110 111 AutoSharedLock(const AutoSharedLock&) = delete; 112 AutoSharedLock(AutoSharedLock&&) = delete; 113 AutoSharedLock& operator=(const AutoSharedLock&) = delete; 114 AutoSharedLock& operator=(AutoSharedLock&&) = delete; 115 116 private: 117 Win32SRWLock& mLock; 118 }; 119 120 class MOZ_RAII AutoExclusiveLock final { 121 public: 122 explicit AutoExclusiveLock(Win32SRWLock& aLock) : mLock(aLock) { 123 mLock.LockExclusive(); 124 } 125 126 ~AutoExclusiveLock() { mLock.UnlockExclusive(); } 127 128 AutoExclusiveLock(const AutoExclusiveLock&) = delete; 129 AutoExclusiveLock(AutoExclusiveLock&&) = delete; 130 AutoExclusiveLock& operator=(const AutoExclusiveLock&) = delete; 131 AutoExclusiveLock& operator=(AutoExclusiveLock&&) = delete; 132 133 private: 134 Win32SRWLock& mLock; 135 }; 136 137 } // namespace glue 138 } // namespace mozilla 139 140 #endif // mozilla_glue_MozglueUtils_h