iced_winit/
proxy.rs
1use crate::futures::futures::{
2 Future, Sink, StreamExt,
3 channel::mpsc,
4 select,
5 task::{Context, Poll},
6};
7use crate::runtime::Action;
8use std::pin::Pin;
9
10#[derive(Debug)]
12pub struct Proxy<T: 'static> {
13 raw: winit::event_loop::EventLoopProxy<Action<T>>,
14 sender: mpsc::Sender<Action<T>>,
15 notifier: mpsc::Sender<usize>,
16}
17
18impl<T: 'static> Clone for Proxy<T> {
19 fn clone(&self) -> Self {
20 Self {
21 raw: self.raw.clone(),
22 sender: self.sender.clone(),
23 notifier: self.notifier.clone(),
24 }
25 }
26}
27
28impl<T: 'static> Proxy<T> {
29 const MAX_SIZE: usize = 100;
30
31 pub fn new(
33 raw: winit::event_loop::EventLoopProxy<Action<T>>,
34 ) -> (Self, impl Future<Output = ()>) {
35 let (notifier, mut processed) = mpsc::channel(Self::MAX_SIZE);
36 let (sender, mut receiver) = mpsc::channel(Self::MAX_SIZE);
37 let proxy = raw.clone();
38
39 let worker = async move {
40 let mut count = 0;
41
42 loop {
43 if count < Self::MAX_SIZE {
44 select! {
45 message = receiver.select_next_some() => {
46 let _ = proxy.send_event(message);
47 count += 1;
48
49 }
50 amount = processed.select_next_some() => {
51 count = count.saturating_sub(amount);
52 }
53 complete => break,
54 }
55 } else {
56 select! {
57 amount = processed.select_next_some() => {
58 count = count.saturating_sub(amount);
59 }
60 complete => break,
61 }
62 }
63 }
64 };
65
66 (
67 Self {
68 raw,
69 sender,
70 notifier,
71 },
72 worker,
73 )
74 }
75
76 pub fn send(&self, value: T)
81 where
82 T: std::fmt::Debug,
83 {
84 self.send_action(Action::Output(value));
85 }
86
87 pub fn send_action(&self, action: Action<T>)
92 where
93 T: std::fmt::Debug,
94 {
95 let _ = self.raw.send_event(action);
96 }
97
98 pub fn free_slots(&mut self, amount: usize) {
101 let _ = self.notifier.start_send(amount);
102 }
103}
104
105impl<T: 'static> Sink<Action<T>> for Proxy<T> {
106 type Error = mpsc::SendError;
107
108 fn poll_ready(
109 mut self: Pin<&mut Self>,
110 cx: &mut Context<'_>,
111 ) -> Poll<Result<(), Self::Error>> {
112 self.sender.poll_ready(cx)
113 }
114
115 fn start_send(
116 mut self: Pin<&mut Self>,
117 action: Action<T>,
118 ) -> Result<(), Self::Error> {
119 self.sender.start_send(action)
120 }
121
122 fn poll_flush(
123 mut self: Pin<&mut Self>,
124 cx: &mut Context<'_>,
125 ) -> Poll<Result<(), Self::Error>> {
126 match self.sender.poll_ready(cx) {
127 Poll::Ready(Err(ref e)) if e.is_disconnected() => {
128 Poll::Ready(Ok(()))
130 }
131 x => x,
132 }
133 }
134
135 fn poll_close(
136 mut self: Pin<&mut Self>,
137 _cx: &mut Context<'_>,
138 ) -> Poll<Result<(), Self::Error>> {
139 self.sender.disconnect();
140 Poll::Ready(Ok(()))
141 }
142}