Problem
I want to write a async future, whose task is waiting some value to become some target value.
Below is my own implementation, which follows the guide: Task Wakeups with Waker - Asynchronous Programming in Rust (rust-lang.github.io) .
My question is this implementation have any space to improve? Do we already have highly-optimized implementation?
My Code
use std::{
sync::{Arc, Mutex},
task::{Poll, Waker},
};
use futures::Future;
#[cfg(test)]
mod tests {
use std::{
sync::{Arc, Mutex},
thread,
time::Duration,
};
use futures::executor::block_on;
use crate::{SharedState, ValueEvent};
#[test]
fn it_works() {
let state = Arc::new(Mutex::new(SharedState {
value: 0,
waker: None,
}));
let thread_shared_state = state.clone();
let test_shared_state = state.clone();
std::thread::spawn(move || loop {
thread::sleep(Duration::from_millis(20));
let mut state = thread_shared_state.lock().unwrap();
state.value += 1;
if let Some(waker) = state.waker.take() {
waker.wake();
}
if state.value >= 200 {
break;
}
});
let value_event = ValueEvent::new(state, 50);
block_on(value_event);
println!("value_event occurred.");
thread::sleep(Duration::from_secs(1));
let state = test_shared_state.lock().unwrap();
println!("end value:{}", state.value);
}
}
struct SharedState<State> {
value: State,
waker: Option<Waker>,
}
struct ValueEvent<Value>
where
Value: PartialEq,
{
shared_state: Arc<Mutex<SharedState<Value>>>,
target: Value,
}
impl<Value: PartialEq> ValueEvent<Value> {
pub fn new(state: Arc<Mutex<SharedState<Value>>>, target: Value) -> Self {
Self {
shared_state: state,
target,
}
}
}
impl<Value: PartialEq> Future for ValueEvent<Value> {
type Output = ();
fn poll(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
let mut shared_state = self.shared_state.lock().unwrap();
if shared_state.value == self.target {
Poll::Ready(())
} else {
shared_state.waker = Some(cx.waker().clone());
Poll::Pending
}
}
}