BTZ5WJPNRJ4Y3JB77XZXQWDZV2SJ4WBMSYPITUYOWSR4GLRHU4GAC ELBXLSZ3LKHEXX7T7FU2EE6UTZI2QXUTV4ZM66PGSKVLHSHXQVWAC O5P6HCPWGMGJBFJEMC3SYQJ5OEW2AQV4KEJCMRVTTS3K6M45Z3BAC OGNLZ5CUNFD7X43S4VTMCCEMJA2R76O35XACIR7AUBHPGME27E3AC DZPGVVKGX6QS4HX5GVF3DR3UZAV2EOMMVRUDEGTR2OPJVDG3FNXQC GKGOXYENXXG6XJXPLXVSWKOYWHZRKNT5JDTAAQ2XWWYGJTLFH5IAC EEO6C4YSWFW3JOZ3JH6K7X4TKAUTVJD53CQNYZHI2QY6REGEXUCAC L6RIUKGLJZLAOKFGUDTZKBPP4HUBPEZAKHJEQHO34WFF62AB2ZIQC X5EMQBC4BFNJOOHS2QMF4UB4QH6JKSALK6RXLK6B7SP6MNYSAP6QC KMU4E426CB2NDRJEK7B4GSL22P62CJPPZRK45X3JV5WP5NIBIGRQC LJD76LBNKTWSAHLRGL7EXNMM5HYRSOD6VXWYQSX2XVK7TQROTZ6QC SSJKQR6X6L2KUJI2YPLMBQU3PTR2RYAQQR6N35MDMOCOTV6ZDUEAC 7CBRRVV3GLVLBHNPQNRHSA2ZCLHIMCHFEMWMZNOICY2OZLB7DGPAC Q6Z5IQJ3SUI7BUJCKT377EPIRO7UVZFI7UB74ZEEGTCTUKC7WGKQC WQIQA2TNWNSNGKQC22XPTECAZEWG6PG5QWQECUVXDUQRSCV6RUZQC GROTV3H2V6BHU5CA7WSLVYDCWAR7GHUP5JV2QOGPLJ6N3553T4MAC DKGUNP6LG3DJ35VMHU42K3VJO5JJ5UVYI4PLM72HO5ZNAQ4P366AC // Poor man's executor for winit's poor man's async// taken from https://github.com/rust-windowing/winit/issues/1199#issuecomment-1685122253type TaskId = usize;#[derive(Debug)]enum PollTask {Task(TaskId),}type BoxedTaskFuture<E> = Box<dyn Future<Output = Result<(), E>>>;struct WinitExecutor<E> {// a better implementation should use a vec of options here.tasks: HashMap<TaskId, Pin<BoxedTaskFuture<E>>>,event_loop_proxy: EventLoopProxy<PollTask>,}impl<E> WinitExecutor<E> {/// Create a new `WinitExecutor`, driven by the given event loop.pub fn new(event_loop_proxy: EventLoopProxy<PollTask>) -> Self {Self {tasks: HashMap::new(),event_loop_proxy,}}fn next_task_id(&self) -> TaskId {static NEXT_TASK_ID: std::sync::atomic::AtomicUsize =std::sync::atomic::AtomicUsize::new(0);NEXT_TASK_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed)}/// Spawn a task.////// This immediately polls the task once, and then schedules it to be/// polled again if needed, using a `UserEvent::PollTask` event.pub fn spawn(&mut self, task: impl Future<Output = Result<(), E>> + 'static) -> Result<(), E> {let task = Box::pin(task);let task_id = self.next_task_id();self.tasks.insert(task_id, task);if let Some(res) = self.poll(task_id) {res} else {self.event_loop_proxy.send_event(PollTask::Task(task_id)).unwrap();Ok(())}}
/// Poll a task.////// Should be called when the event loop receives a `UserEvent::PollTask`.pub fn poll(&mut self, task_id: TaskId) -> Option<Result<(), E>> {// this wake only need to work once, I believe, so we could use some type of "oneshot box"// instead of a mutex?let winit_proxy = Mutex::new(self.event_loop_proxy.clone());let waker = waker_fn::waker_fn(move || {let _ = winit_proxy.lock().unwrap().send_event(PollTask::Task(task_id));});let task = self.tasks.get_mut(&task_id).unwrap().as_mut();match task.poll(&mut Context::from_waker(&waker)) {Poll::Ready(res) => {_ = self.tasks.remove(&task_id);Some(res)}Poll::Pending => None,}}/// Retrieves the game lockfn get_lock<'a, S>(&'a mut self, game: &'a AsyncMutex<Game<S>>) -> AsyncMutexGuard<Game<S>>whereS: 'static,{let winit_proxy = Mutex::new(self.event_loop_proxy.clone());let (tx, rx) = flume::bounded(1);let waker = waker_fn::waker_fn(move || {let id_to_poll = rx.recv().unwrap();let _ = winit_proxy.lock().unwrap().send_event(PollTask::Task(id_to_poll));});// self.lock_tasks.push_back(Box::pin(game.lock_arc()));loop {// Continuously try to get the lock until we succeedlet fut = game.lock();let fut = pin!(fut);let poll_status = fut.poll(&mut Context::from_waker(&waker));if let Poll::Ready(res) = poll_status {break res;}// Drive the task loopif let Some(id) = self.tasks.keys().next().copied() {tx.send(id).unwrap();}}}fn get_lock_owned<S>(&mut self, game: Arc<AsyncMutex<Game<S>>>) -> AsyncMutexGuardOwned<Game<S>>whereS: 'static,{let winit_proxy = Mutex::new(self.event_loop_proxy.clone());let (tx, rx) = flume::unbounded();let waker = waker_fn::waker_fn(move || {let id_to_poll = rx.recv().unwrap();let _ = winit_proxy.lock().unwrap().send_event(PollTask::Task(id_to_poll));});// self.lock_tasks.push_back(Box::pin(game.lock_arc()));let mut fut = Box::pin(game.lock_arc());loop {let fut = pin!(fut.as_mut());let poll_status = fut.poll(&mut Context::from_waker(&waker));if let Poll::Ready(res) = poll_status {break res;}// Drive the task loopif let Some(id) = self.tasks.keys().next().copied() {tx.send(id).unwrap();}}}}
let mut game = winit_executor.get_lock_owned(game.clone());winit_executor.spawn({async move {let future = game.create_surface();future.await}}).unwrap();}Event::UserEvent(poll_task) => {match poll_task {// a certain task needs pollingPollTask::Task(tid) => {if let Some(res) = winit_executor.poll(tid) {// the stuff here shouldn't failres.unwrap()}}}
let game = game.clone();let assets = assets.clone();outer_cosync.queue(|_input: cosync::CosyncInput<()>| async move {game.try_lock().unwrap().create_surface(&assets).await.unwrap();})
name = "poll-promise"version = "0.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5f6a58fecbf9da8965bcdb20ce4fd29788d1acee68ddbb64f0ba1b81bccdb7df"dependencies = ["document-features","static_assertions","wasm-bindgen","wasm-bindgen-futures",][[package]]