winit_runtime/executor/
handle.rs1use std::thread::{self, ThreadId};
8
9use async_task::{Runnable, Task};
10use futures_intrusive::timer::TimerFuture;
11use futures_lite::Future;
12use instant::Duration;
13use parking_lot::Mutex;
14use winit::event_loop::{EventLoop, EventLoopProxy};
15
16use crate::timer::ExecutorTimer;
17
18use super::event::ExecutorEvent;
19
20#[derive(Debug)]
22pub struct ExecutorHandle {
23 thread_id: ThreadId,
24 proxy: Mutex<EventLoopProxy<ExecutorEvent>>,
25
26 pub(super) timer: ExecutorTimer,
27}
28
29impl ExecutorHandle {
30 pub(crate) fn new(event_loop: &EventLoop<ExecutorEvent>) -> Self {
31 Self {
32 thread_id: thread::current().id(),
33 proxy: Mutex::new(event_loop.create_proxy()),
34
35 timer: ExecutorTimer::new(),
36 }
37 }
38
39 pub async fn exit(&self) -> ! {
41 self.proxy.lock().send_event(ExecutorEvent::Exit).unwrap();
42 futures_lite::future::pending().await
43 }
44
45 pub fn wait(&self, delay: Duration) -> TimerFuture {
47 let fut = self.timer.delay(delay);
48
49 self.proxy.lock().send_event(ExecutorEvent::Wake).unwrap();
50
51 fut
52 }
53
54 pub fn wait_deadline(&self, timestamp: u64) -> TimerFuture {
56 let fut = self.timer.deadline(timestamp);
57
58 self.proxy.lock().send_event(ExecutorEvent::Wake).unwrap();
59
60 fut
61 }
62
63 pub fn spawn<Fut>(&self, fut: Fut) -> Task<Fut::Output>
67 where
68 Fut: Future + Send + 'static,
69 Fut::Output: Send + 'static,
70 {
71 unsafe { self.spawn_unchecked(fut) }
73 }
74
75 pub fn spawn_local<Fut>(&self, fut: Fut) -> Task<Fut::Output>
80 where
81 Fut: Future + 'static,
82 Fut::Output: 'static,
83 {
84 if thread::current().id() != self.thread_id {
85 panic!("Cannot call spawn_local outside of event loop thread");
86 }
87
88 unsafe { self.spawn_unchecked(fut) }
90 }
91
92 pub unsafe fn spawn_unchecked<Fut>(&self, fut: Fut) -> Task<Fut::Output>
99 where
100 Fut: Future,
101 {
102 let (runnable, task) = self.spawn_raw_unchecked(fut);
103 runnable.schedule();
104
105 task
106 }
107
108 pub(super) unsafe fn spawn_raw_unchecked<Fut>(&self, fut: Fut) -> (Runnable, Task<Fut::Output>)
111 where
112 Fut: Future,
113 {
114 let proxy = self.proxy.lock().clone();
115
116 async_task::spawn_unchecked(fut, move |runnable| {
117 let _ = proxy.send_event(ExecutorEvent::PollTask(runnable));
118 })
119 }
120}