1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 #include "mozilla/Logging.h"
9 #include "WindowsMutex.h"
11 namespace mozilla::default_agent
{
13 using mozilla::LogLevel
;
15 static LazyLogModule
gWindowsMutexLog("WindowsMutex");
17 NS_IMPL_ISUPPORTS(WindowsMutexFactory
, nsIWindowsMutexFactory
)
20 WindowsMutexFactory::CreateMutex(const nsAString
& aName
,
21 nsIWindowsMutex
** aWindowsMutex
) {
23 auto name
= PromiseFlatString(aName
);
25 mutex
.own(CreateMutexW(nullptr, FALSE
, name
.get()));
26 if (mutex
.get() == nullptr) {
27 MOZ_LOG(gWindowsMutexLog
, LogLevel::Error
,
28 ("Couldn't open mutex \"%s\": %#lX",
29 NS_ConvertUTF16toUTF8(name
).get(), GetLastError()));
30 return NS_ERROR_NOT_AVAILABLE
;
33 RefPtr
<WindowsMutex
> nsMutex
= new WindowsMutex(name
, mutex
);
34 nsMutex
.forget(aWindowsMutex
);
38 WindowsMutex::WindowsMutex(const nsString
& aName
, nsAutoHandle
& aMutex
)
39 : mName(NS_ConvertUTF16toUTF8(aName
)), mLocked(false) {
43 WindowsMutex::~WindowsMutex() {
45 // nsAutoHandle will take care of closing the mutex's handle.
48 NS_IMPL_ISUPPORTS(WindowsMutex
, nsIWindowsMutex
)
51 WindowsMutex::TryLock() {
52 // This object may be used on the main thread, so don't wait if it's
54 DWORD mutexStatus
= WaitForSingleObject(mMutex
.get(), 0);
55 if (mutexStatus
== WAIT_OBJECT_0
) {
57 } else if (mutexStatus
== WAIT_TIMEOUT
) {
58 MOZ_LOG(gWindowsMutexLog
, LogLevel::Warning
,
59 ("Timed out waiting for mutex \"%s\"", mName
.get()));
60 } else if (mutexStatus
== WAIT_ABANDONED
) {
61 // This status code means that we are supposed to check our data for
62 // consistency as the last locking process didn't signal intentional
63 // unlocking which might indicate it crashed mid-operation. Current uses of
64 // this `WindowsMutex` don't need to worry about corruption of the locked
65 // object, if needed the `nsIWindowsMutex` interface should be extended.
66 MOZ_LOG(gWindowsMutexLog
, LogLevel::Warning
,
67 ("Found abandoned mutex \"%s\". Continuing...", mName
.get()));
70 // The only other documented status code is WAIT_FAILED. In the case that
71 // we somehow get some other code, that is also an error.
72 MOZ_LOG(gWindowsMutexLog
, LogLevel::Error
,
73 ("Failed to wait on mutex: mName: %s, error %#lX", mName
.get(),
76 return mLocked
? NS_OK
: NS_ERROR_NOT_AVAILABLE
;
80 WindowsMutex::IsLocked(bool* aLocked
) {
86 WindowsMutex::Unlock() {
90 BOOL success
= ReleaseMutex(mMutex
.get());
92 MOZ_LOG(gWindowsMutexLog
, LogLevel::Error
,
93 ("Failed to release mutex \"%s\"", mName
.get()));
94 rv
= NS_ERROR_UNEXPECTED
;
103 } // namespace mozilla::default_agent