File
Blob: src/workerd/util/xthreadnotifier.h
| 1 | // Copyright (c) 2017-2022 Cloudflare, Inc. |
| 2 | // Licensed under the Apache 2.0 license found in the LICENSE file or at: |
| 3 | // https://opensource.org/licenses/Apache-2.0 |
| 4 | |
| 5 | #pragma once |
| 6 | |
| 7 | #include <kj/async.h> |
| 8 | #include <kj/mutex.h> |
| 9 | |
| 10 | namespace workerd { |
| 11 | |
| 12 | class XThreadNotifier final: public kj::AtomicRefcounted { |
| 13 | // Class encapsulating the ability to notify a waiting thread from other threads. |
| 14 | // |
| 15 | // TODO(cleanup): Can this be consolidated with wait-list.h? |
| 16 | // |
| 17 | // TODO(cleanup): This could be a lot simpler if only it were possible to cancel |
| 18 | // an executor.executeAsync() promise from an arbitrary thread. Then, if the inspector |
| 19 | // session was destroyed in its thread while a cross-thread notification was in-flight, it |
| 20 | // could cancel that notification directly. |
| 21 | public: |
| 22 | static inline kj::Own<XThreadNotifier> create() { |
| 23 | return kj::atomicRefcounted<XThreadNotifier>(); |
| 24 | } |
| 25 | |
| 26 | XThreadNotifier(): paf(kj::newPromiseAndCrossThreadFulfiller<void>()) {} |
| 27 | |
| 28 | kj::Promise<void> awaitNotification() { |
| 29 | auto promise = kj::mv(paf.lockExclusive()->promise); |
| 30 | co_await promise; |
| 31 | auto lockedPaf = paf.lockExclusive(); |
| 32 | auto nextPaf = kj::newPromiseAndCrossThreadFulfiller<void>(); |
| 33 | lockedPaf->promise = kj::mv(nextPaf.promise); |
| 34 | lockedPaf->fulfiller = kj::mv(nextPaf.fulfiller); |
| 35 | } |
| 36 | |
| 37 | void notify() const { |
| 38 | paf.lockExclusive()->fulfiller->fulfill(); |
| 39 | } |
| 40 | |
| 41 | private: |
| 42 | kj::MutexGuarded<kj::PromiseCrossThreadFulfillerPair<void>> paf; |
| 43 | }; |
| 44 | |
| 45 | } // namespace workerd |