1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et ft=cpp : */
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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_ipc_AsyncBlockers_h
8 #define mozilla_ipc_AsyncBlockers_h
10 #include "mozilla/MozPromise.h"
11 #include "mozilla/ThreadSafety.h"
14 // FIXME: when bug 1760855 is fixed, it should not be required anymore
16 namespace mozilla::ipc
{
19 * AsyncBlockers provide a simple registration service that allows to suspend
20 * completion of a particular task until all registered entries have been
21 * cleared. This can be used to implement a similar service to
22 * nsAsyncShutdownService in processes where it wouldn't normally be available.
23 * This class is thread-safe.
28 : mLock("AsyncRegistrar"),
29 mPromise(new GenericPromise::Private(__func__
)) {}
30 void Register(void* aBlocker
) {
31 MutexAutoLock
lock(mLock
);
32 mBlockers
.InsertElementSorted(aBlocker
);
34 void Deregister(void* aBlocker
) {
35 MutexAutoLock
lock(mLock
);
36 MOZ_ASSERT(mBlockers
.ContainsSorted(aBlocker
));
37 MOZ_ALWAYS_TRUE(mBlockers
.RemoveElementSorted(aBlocker
));
40 RefPtr
<GenericPromise
> WaitUntilClear(uint32_t aTimeOutInMs
= 0) {
42 MutexAutoLock
lock(mLock
);
46 if (aTimeOutInMs
> 0) {
47 GetCurrentSerialEventTarget()->DelayedDispatch(
48 NS_NewRunnableFunction("AsyncBlockers::WaitUntilClear",
49 [promise
= mPromise
]() {
50 // The AsyncBlockers object may have been
51 // deleted by now and the object isn't
52 // refcounted (nor do we want it to be). We
53 // can unconditionally resolve the promise
54 // even it has already been resolved as
55 // MozPromise are thread-safe and will just
56 // ignore the action if already resolved.
57 promise
->Resolve(true, __func__
);
65 virtual ~AsyncBlockers() { mPromise
->Resolve(true, __func__
); }
68 void MaybeResolve() MOZ_REQUIRES(mLock
) {
69 mLock
.AssertCurrentThreadOwns();
70 if (!mBlockers
.IsEmpty()) {
73 mPromise
->Resolve(true, __func__
);
76 nsTArray
<void*> mBlockers
MOZ_GUARDED_BY(mLock
);
77 const RefPtr
<GenericPromise::Private
> mPromise
;
80 } // namespace mozilla::ipc
82 #endif // mozilla_ipc_AsyncBlockers_h