use std::{fmt::Debug, task::Waker};
pub struct ReadyFutureState<T> {
pub(crate) waker: Option<Waker>,
pub(crate) result: ReadyFutureResult<T>,
}
impl<T> ReadyFutureState<T> {
pub fn new() -> ReadyFutureState<T> {
ReadyFutureState {
waker: None,
result: ReadyFutureResult::Pending,
}
}
pub fn new_completed(value: T) -> ReadyFutureState<T> {
ReadyFutureState {
waker: None,
result: ReadyFutureResult::Completed(value),
}
}
pub fn is_fulfilled(&self) -> bool {
!self.is_pending()
}
pub fn is_aborted(&self) -> bool {
matches!(self.result, ReadyFutureResult::Aborted)
}
pub fn is_timeouted(&self) -> bool {
matches!(self.result, ReadyFutureResult::Timeout)
}
pub fn is_terminated(&self) -> bool {
matches!(self.result, ReadyFutureResult::Terminated)
}
pub fn is_pending(&self) -> bool {
matches!(self.result, ReadyFutureResult::Pending)
}
pub fn is_completed(&self) -> bool {
matches!(self.result, ReadyFutureResult::Completed(_))
}
pub fn abort(&mut self) {
self.result = ReadyFutureResult::Aborted;
self.wake();
}
pub fn timeout(&mut self) {
self.result = ReadyFutureResult::Timeout;
self.wake();
}
pub fn complete(&mut self, val: T) {
self.result = ReadyFutureResult::Completed(val);
self.wake();
}
pub(crate) fn wake(&mut self) {
if let Some(waker) = self.waker.take() {
waker.wake()
}
}
pub fn terminate(&mut self) {
self.result = ReadyFutureResult::Terminated;
}
}
#[derive(Clone, Debug)]
pub enum ReadyFutureResult<T> {
Completed(T),
Timeout,
Aborted,
Pending,
Terminated,
}
impl<T: Debug> Debug for ReadyFutureState<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ReadyFutureState")
.field("waker", &self.waker)
.field("result", &self.result)
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicBool, Ordering};
use std::task::Wake;
struct TestWaker {
woken: std::sync::Arc<AtomicBool>,
}
impl Wake for TestWaker {
fn wake(self: std::sync::Arc<Self>) {
self.woken.store(true, Ordering::SeqCst);
}
}
#[test]
fn test_new_state() {
let state = ReadyFutureState::<i32>::new();
assert!(state.is_pending());
assert!(!state.is_fulfilled());
assert!(!state.is_completed());
assert!(!state.is_aborted());
assert!(!state.is_timeouted());
assert!(!state.is_terminated());
assert!(state.waker.is_none());
}
#[test]
fn test_new_completed_state() {
let state = ReadyFutureState::new_completed(42);
assert!(!state.is_pending());
assert!(state.is_fulfilled());
assert!(state.is_completed());
assert!(!state.is_aborted());
assert!(!state.is_timeouted());
assert!(!state.is_terminated());
assert!(state.waker.is_none());
}
#[test]
fn test_abort() {
let mut state = ReadyFutureState::<i32>::new();
assert!(state.is_pending());
state.abort();
assert!(!state.is_pending());
assert!(state.is_fulfilled());
assert!(state.is_aborted());
assert!(!state.is_completed());
assert!(!state.is_timeouted());
assert!(!state.is_terminated());
}
#[test]
fn test_timeout() {
let mut state = ReadyFutureState::<i32>::new();
assert!(state.is_pending());
state.timeout();
assert!(!state.is_pending());
assert!(state.is_fulfilled());
assert!(state.is_timeouted());
assert!(!state.is_completed());
assert!(!state.is_aborted());
assert!(!state.is_terminated());
}
#[test]
fn test_complete() {
let mut state = ReadyFutureState::<i32>::new();
assert!(state.is_pending());
state.complete(123);
assert!(!state.is_pending());
assert!(state.is_fulfilled());
assert!(state.is_completed());
assert!(!state.is_aborted());
assert!(!state.is_timeouted());
assert!(!state.is_terminated());
}
#[test]
fn test_terminate() {
let mut state = ReadyFutureState::<i32>::new();
assert!(state.is_pending());
state.terminate();
assert!(!state.is_pending());
assert!(state.is_fulfilled());
assert!(state.is_terminated());
assert!(!state.is_completed());
assert!(!state.is_aborted());
assert!(!state.is_timeouted());
}
#[test]
fn test_waker_invocation_on_abort() {
let mut state = ReadyFutureState::<i32>::new();
let woken = std::sync::Arc::new(AtomicBool::new(false));
let waker = std::sync::Arc::new(TestWaker {
woken: woken.clone(),
});
let waker = std::task::Waker::from(waker);
state.waker = Some(waker);
assert!(!woken.load(Ordering::SeqCst));
state.abort();
assert!(woken.load(Ordering::SeqCst));
assert!(state.waker.is_none()); }
#[test]
fn test_waker_invocation_on_timeout() {
let mut state = ReadyFutureState::<i32>::new();
let woken = std::sync::Arc::new(AtomicBool::new(false));
let waker = std::sync::Arc::new(TestWaker {
woken: woken.clone(),
});
let waker = std::task::Waker::from(waker);
state.waker = Some(waker);
assert!(!woken.load(Ordering::SeqCst));
state.timeout();
assert!(woken.load(Ordering::SeqCst));
assert!(state.waker.is_none()); }
#[test]
fn test_waker_invocation_on_complete() {
let mut state = ReadyFutureState::<i32>::new();
let woken = std::sync::Arc::new(AtomicBool::new(false));
let waker = std::sync::Arc::new(TestWaker {
woken: woken.clone(),
});
let waker = std::task::Waker::from(waker);
state.waker = Some(waker);
assert!(!woken.load(Ordering::SeqCst));
state.complete(456);
assert!(woken.load(Ordering::SeqCst));
assert!(state.waker.is_none()); }
#[test]
fn test_no_waker_no_invocation() {
let mut state = ReadyFutureState::<i32>::new();
let woken = std::sync::Arc::new(AtomicBool::new(false));
let waker = std::sync::Arc::new(TestWaker {
woken: woken.clone(),
});
let _waker = std::task::Waker::from(waker);
assert!(state.waker.is_none());
assert!(!woken.load(Ordering::SeqCst));
state.abort();
assert!(!woken.load(Ordering::SeqCst)); }
#[test]
fn test_ready_future_result_debug() {
let result = ReadyFutureResult::Completed(42);
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("Completed"));
assert!(debug_str.contains("42"));
let result = ReadyFutureResult::<i32>::Pending;
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("Pending"));
let result = ReadyFutureResult::<i32>::Aborted;
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("Aborted"));
let result = ReadyFutureResult::<i32>::Timeout;
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("Timeout"));
let result = ReadyFutureResult::<i32>::Terminated;
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("Terminated"));
}
#[test]
fn test_ready_future_result_clone() {
let result1 = ReadyFutureResult::Completed(42);
let result2 = result1.clone();
match (result1, result2) {
(ReadyFutureResult::Completed(v1), ReadyFutureResult::Completed(v2)) => {
assert_eq!(v1, v2);
}
_ => panic!("Clone should preserve the value"),
}
let result1 = ReadyFutureResult::<i32>::Pending;
let result2 = result1.clone();
assert!(matches!(result1, ReadyFutureResult::Pending));
assert!(matches!(result2, ReadyFutureResult::Pending));
}
#[test]
fn test_state_debug_formatting() {
let state = ReadyFutureState::<i32>::new();
let debug_str = format!("{:?}", state);
assert!(debug_str.contains("ReadyFutureState"));
assert!(debug_str.contains("waker"));
assert!(debug_str.contains("result"));
}
}