gwr_engine/events/
repeated.rs

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