gwr_engine/events/
once.rs

1// Copyright (c) 2023 Graphcore Ltd. All rights reserved.
2
3//! An event that can only be triggered once
4
5use std::cell::RefCell;
6use std::pin::Pin;
7use std::rc::Rc;
8use std::task::{Context, Poll, Waker};
9
10use futures::Future;
11use futures::future::FusedFuture;
12
13use crate::sim_error;
14use crate::traits::{BoxFuture, Event};
15use crate::types::SimResult;
16
17pub struct OnceState<T>
18where
19    T: Copy,
20{
21    listen_waiting: RefCell<Vec<Waker>>,
22    triggered: RefCell<bool>,
23    result: T,
24}
25
26impl<T> OnceState<T>
27where
28    T: Copy,
29{
30    pub fn new(value: T) -> Self {
31        Self {
32            listen_waiting: RefCell::new(Vec::new()),
33            triggered: RefCell::new(false),
34            result: value,
35        }
36    }
37}
38
39impl Default for OnceState<()> {
40    fn default() -> Self {
41        Self::new(())
42    }
43}
44
45#[derive(Clone)]
46pub struct Once<T>
47where
48    T: Copy,
49{
50    state: Rc<OnceState<T>>,
51}
52
53pub struct OnceFuture<T>
54where
55    T: Copy,
56{
57    state: Rc<OnceState<T>>,
58    done: bool,
59}
60
61impl<T> FusedFuture for OnceFuture<T>
62where
63    T: Copy,
64{
65    fn is_terminated(&self) -> bool {
66        self.done
67    }
68}
69
70impl<T> Once<T>
71where
72    T: Copy,
73{
74    pub fn with_value(value: T) -> Self {
75        Self {
76            state: Rc::new(OnceState::new(value)),
77        }
78    }
79
80    pub fn notify(&self) -> SimResult {
81        if *self.state.triggered.borrow() {
82            return sim_error!("once event already triggered");
83        }
84        *self.state.triggered.borrow_mut() = true;
85        for waker in self.state.listen_waiting.borrow_mut().drain(..) {
86            waker.wake();
87        }
88        Ok(())
89    }
90}
91
92impl<T> Once<T>
93where
94    T: Copy + 'static,
95{
96    pub fn new(value: T) -> Self {
97        Self {
98            state: Rc::new(OnceState::new(value)),
99        }
100    }
101}
102
103impl Default for Once<()> {
104    fn default() -> Self {
105        Self::new(())
106    }
107}
108
109impl<T> Event<T> for Once<T>
110where
111    T: Copy + 'static,
112{
113    fn listen(&self) -> BoxFuture<'static, T> {
114        Box::pin(OnceFuture {
115            state: self.state.clone(),
116            done: false,
117        })
118    }
119
120    /// Allow cloning of Boxed elements of vector
121    fn clone_dyn(&self) -> Box<dyn Event<T>> {
122        Box::new(self.clone())
123    }
124}
125
126impl<T> Future for OnceFuture<T>
127where
128    T: Copy,
129{
130    type Output = T;
131
132    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
133        if *self.state.triggered.borrow() {
134            self.done = true;
135            Poll::Ready(self.state.result)
136        } else {
137            self.state
138                .listen_waiting
139                .borrow_mut()
140                .push(cx.waker().clone());
141            Poll::Pending
142        }
143    }
144}