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 WinHandleWatcher_h__
8 #define WinHandleWatcher_h__
10 #include <minwindef.h>
12 #include "mozilla/AlreadyAddRefed.h"
13 #include "mozilla/RefPtr.h"
14 #include "mozilla/UniquePtr.h"
16 #include "nsIEventTarget.h"
17 #include "nsIRunnable.h"
18 #include "nsIThread.h"
19 #include "nsThreadUtils.h"
22 ///////////////////////////////////////////////////////////////////////
25 // Enqueues a task onto an event target when a watched Win32 synchronization
26 // object [1] enters the signaled state.
28 // The HandleWatcher must be stopped before either it or the synchronization
29 // object is destroyed.
39 // HANDLE CreateThing();
43 // mHandle.set(CreateThing());
45 // mHandle.get(), NS_GetCurrentThread(), // (or any other thread)
46 // NS_NewRunnableFunction("OnComplete", [this] { OnComplete(); }));
49 // ~MyClass() { mWatcher.Stop(); }
51 // HandleWatcher mWatcher;
52 // HandlePtr mHandle; // calls ::CloseHandle() on destruction
56 // Note: this example demonstrates why an explicit `Stop()` is necessary in
57 // MyClass's destructor. Without it, the `HandlePtr` would destroy the HANDLE --
58 // and possibly whatever other data `OnComplete()` depends on -- before the
61 // Rather than make code correctness silently dependent on member object order,
62 // we require that HandleWatcher already be stopped at its destruction time.
63 // (This does not guarantee correctness, as the task may still reference a
64 // partially-destroyed transitive owner; but, short of RIIR, a guarantee of
65 // correctness is probably not possible here.)
69 // [1]https://learn.microsoft.com/en-us/windows/win32/sync/synchronization-objects
77 HandleWatcher(HandleWatcher
const&) = delete;
78 HandleWatcher
& operator=(HandleWatcher
const&) = delete;
80 HandleWatcher(HandleWatcher
&&) noexcept
;
81 HandleWatcher
& operator=(HandleWatcher
&&) noexcept
;
83 // Watches the given Win32 HANDLE, which must be a synchronization object. As
84 // soon as the HANDLE is signaled, posts `aRunnable` to `aTarget`.
86 // `aHandle` is merely borrowed for the duration of the watch: the
87 // HandleWatcher does not attempt to close it, and its lifetime must exceed
90 // If the watch is stopped for any reason other than completion, `aRunnable`
91 // is released immediately, on the same thread from which the Watch was
94 // The watch is stopped when any of the following occurs:
95 // * `Stop()` is called.
96 // * `Watch()` is called again, even without an intervening `Stop()`.
97 // * This object is destroyed.
98 // * `aTarget` shuts down.
99 // * `aHandle` becomes signaled.
101 void Watch(HANDLE aHandle
, nsIEventTarget
* aTarget
,
102 already_AddRefed
<nsIRunnable
> aRunnable
);
104 // Cancels the current watch, if any.
106 // Idempotent. Thread-safe with respect to other calls of `Stop()`.
109 // Potentially racy. Only intended for tests.
115 } // namespace mozilla
117 #endif // WinHandleWatcher_h__