Skip to content

Commit 710a6a8

Browse files
BerrysoftCopilot
andauthored
feat(notify): move from compio-runtime (#10)
* feat(notify): spsc notifier * docs(notify): fix old names * fix(notify): apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat(notify): rename to AsyncFlag --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d4b6e57 commit 710a6a8

4 files changed

Lines changed: 136 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ mutex = ["dep:slab"]
2323
waker_slot = ["dep:futures-util"]
2424
event = ["dep:event-listener", "dep:local-event"]
2525
bilock = ["waker_slot"]
26+
async_flag = ["waker_slot"]
2627

2728
[dev-dependencies]
2829
futures = { version = "0.3.31", features = ["executor"] }

src/async_flag.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/// Multithreaded notifier
2+
pub mod sync {
3+
super::impl_notify!(sync);
4+
5+
impl crate::AssertMt for AsyncFlag {}
6+
impl crate::AssertMt for AsyncFlagHandle {}
7+
}
8+
9+
/// Singlethreaded notifier
10+
pub mod unsync {
11+
super::impl_notify!(unsync);
12+
}
13+
14+
macro_rules! impl_notify {
15+
($sync:ident) => {
16+
use std::{
17+
pin::Pin,
18+
task::{Context, Poll},
19+
};
20+
21+
use crate::$sync::{flag::Flag, shared::Shared, waker_slot::WakerSlot};
22+
23+
#[derive(Debug)]
24+
struct Inner {
25+
waker: WakerSlot,
26+
set: Flag,
27+
}
28+
29+
#[derive(Debug, Clone)]
30+
struct AsyncFlagImpl(Shared<Inner>);
31+
32+
impl AsyncFlagImpl {
33+
pub fn new() -> Self {
34+
Self(Shared::new(Inner {
35+
waker: WakerSlot::new(),
36+
set: Flag::new(false),
37+
}))
38+
}
39+
40+
pub fn notify(&self) {
41+
self.0.set.swap(true);
42+
self.0.waker.wake();
43+
}
44+
45+
pub fn notified(&self) -> bool {
46+
self.0.set.get()
47+
}
48+
}
49+
50+
impl Future for AsyncFlagImpl {
51+
type Output = ();
52+
53+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
54+
// quick check to avoid registration if already done.
55+
if self.0.set.get() {
56+
return Poll::Ready(());
57+
}
58+
59+
self.0.waker.register(cx.waker());
60+
61+
// Need to check condition **after** `register` to avoid a race
62+
// condition that would result in lost notifications.
63+
if self.0.set.get() {
64+
Poll::Ready(())
65+
} else {
66+
Poll::Pending
67+
}
68+
}
69+
}
70+
71+
/// An event that won't wake until [`AsyncFlagHandle::notify`] is called
72+
/// successfully.
73+
#[derive(Debug)]
74+
pub struct AsyncFlag {
75+
flag: AsyncFlagImpl,
76+
}
77+
78+
impl Default for AsyncFlag {
79+
fn default() -> Self {
80+
Self::new()
81+
}
82+
}
83+
84+
impl AsyncFlag {
85+
/// Create [`AsyncFlag`].
86+
pub fn new() -> Self {
87+
Self {
88+
flag: AsyncFlagImpl::new(),
89+
}
90+
}
91+
92+
/// Get a handle to notify the flag.
93+
pub fn handle(&self) -> AsyncFlagHandle {
94+
AsyncFlagHandle::new(self.flag.clone())
95+
}
96+
97+
/// Returns whether the event has been notified.
98+
pub fn notified(&self) -> bool {
99+
self.flag.notified()
100+
}
101+
102+
/// Wait for [`AsyncFlagHandle::notify`] to be called.
103+
pub async fn wait(self) {
104+
self.flag.await
105+
}
106+
}
107+
108+
/// A wake up handle to [`AsyncFlag`].
109+
pub struct AsyncFlagHandle {
110+
flag: AsyncFlagImpl,
111+
}
112+
113+
impl AsyncFlagHandle {
114+
fn new(flag: AsyncFlagImpl) -> Self {
115+
Self { flag }
116+
}
117+
118+
/// Notify the event.
119+
pub fn notify(self) {
120+
self.flag.notify()
121+
}
122+
}
123+
};
124+
}
125+
126+
use impl_notify;

src/flag.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ macro_rules! impl_flag {
1919
use crate::$sync::atomic::AtomicBool;
2020

2121
/// A boolean flag
22+
#[derive(Debug)]
2223
pub struct Flag(AtomicBool);
2324

2425
impl Flag {

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#![warn(missing_docs)]
4242
#![deny(rustdoc::broken_intra_doc_links)]
4343

44+
#[cfg(feature = "async_flag")]
45+
mod async_flag;
4446
#[cfg(feature = "bilock")]
4547
mod bilock;
4648
#[cfg(feature = "event")]
@@ -62,6 +64,9 @@ pub mod sync {
6264
#[cfg(feature = "watch")]
6365
pub use see::sync as watch;
6466

67+
#[doc(inline)]
68+
#[cfg(feature = "async_flag")]
69+
pub use crate::async_flag::sync as notify;
6570
#[doc(inline)]
6671
#[cfg(feature = "bilock")]
6772
pub use crate::bilock::sync as bilock;
@@ -88,6 +93,9 @@ pub mod unsync {
8893
#[cfg(feature = "watch")]
8994
pub use see::unsync as watch;
9095

96+
#[doc(inline)]
97+
#[cfg(feature = "async_flag")]
98+
pub use crate::async_flag::unsync as notify;
9199
#[doc(inline)]
92100
#[cfg(feature = "bilock")]
93101
pub use crate::bilock::unsync as bilock;

0 commit comments

Comments
 (0)