1*112112d4SAlex Crichton use super::Ctx;
2*112112d4SAlex Crichton use futures::future;
3*112112d4SAlex Crichton use std::ops::DerefMut;
4*112112d4SAlex Crichton use std::sync::{Arc, Mutex};
5*112112d4SAlex Crichton use std::task::{Poll, Waker};
6*112112d4SAlex Crichton use wasmtime::component::{Accessor, Resource};
7*112112d4SAlex Crichton 
8*112112d4SAlex Crichton pub mod bindings {
9*112112d4SAlex Crichton     wasmtime::component::bindgen!({
10*112112d4SAlex Crichton         path: "wit",
11*112112d4SAlex Crichton         world: "yield-runner",
12*112112d4SAlex Crichton         imports: { default: trappable },
13*112112d4SAlex Crichton         with: {
14*112112d4SAlex Crichton             "local:local/ready.thing": super::Thing,
15*112112d4SAlex Crichton         },
16*112112d4SAlex Crichton     });
17*112112d4SAlex Crichton }
18*112112d4SAlex Crichton 
19*112112d4SAlex Crichton #[derive(Default)]
20*112112d4SAlex Crichton pub struct Thing {
21*112112d4SAlex Crichton     wakers: Arc<Mutex<Option<Vec<Waker>>>>,
22*112112d4SAlex Crichton }
23*112112d4SAlex Crichton 
24*112112d4SAlex Crichton impl bindings::local::local::continue_::Host for Ctx {
set_continue(&mut self, v: bool) -> wasmtime::Result<()>25*112112d4SAlex Crichton     fn set_continue(&mut self, v: bool) -> wasmtime::Result<()> {
26*112112d4SAlex Crichton         self.continue_ = v;
27*112112d4SAlex Crichton         Ok(())
28*112112d4SAlex Crichton     }
29*112112d4SAlex Crichton 
get_continue(&mut self) -> wasmtime::Result<bool>30*112112d4SAlex Crichton     fn get_continue(&mut self) -> wasmtime::Result<bool> {
31*112112d4SAlex Crichton         Ok(self.continue_)
32*112112d4SAlex Crichton     }
33*112112d4SAlex Crichton }
34*112112d4SAlex Crichton 
35*112112d4SAlex Crichton impl bindings::local::local::ready::HostThing for Ctx {
new(&mut self) -> wasmtime::Result<Resource<Thing>>36*112112d4SAlex Crichton     fn new(&mut self) -> wasmtime::Result<Resource<Thing>> {
37*112112d4SAlex Crichton         Ok(self.table.push(Thing::default())?)
38*112112d4SAlex Crichton     }
39*112112d4SAlex Crichton 
set_ready(&mut self, thing: Resource<Thing>, ready: bool) -> wasmtime::Result<()>40*112112d4SAlex Crichton     fn set_ready(&mut self, thing: Resource<Thing>, ready: bool) -> wasmtime::Result<()> {
41*112112d4SAlex Crichton         let thing = self.table.get(&thing)?;
42*112112d4SAlex Crichton         let mut wakers = thing.wakers.lock().unwrap();
43*112112d4SAlex Crichton         if ready {
44*112112d4SAlex Crichton             if let Some(wakers) = wakers.take() {
45*112112d4SAlex Crichton                 for waker in wakers {
46*112112d4SAlex Crichton                     waker.wake();
47*112112d4SAlex Crichton                 }
48*112112d4SAlex Crichton             }
49*112112d4SAlex Crichton         } else if wakers.is_none() {
50*112112d4SAlex Crichton             *wakers = Some(Vec::new());
51*112112d4SAlex Crichton         }
52*112112d4SAlex Crichton         Ok(())
53*112112d4SAlex Crichton     }
54*112112d4SAlex Crichton 
drop(&mut self, thing: Resource<Thing>) -> wasmtime::Result<()>55*112112d4SAlex Crichton     fn drop(&mut self, thing: Resource<Thing>) -> wasmtime::Result<()> {
56*112112d4SAlex Crichton         self.table.delete(thing)?;
57*112112d4SAlex Crichton         Ok(())
58*112112d4SAlex Crichton     }
59*112112d4SAlex Crichton }
60*112112d4SAlex Crichton 
61*112112d4SAlex Crichton impl bindings::local::local::ready::HostThingWithStore for Ctx {
when_ready<T>( accessor: &Accessor<T, Self>, thing: Resource<Thing>, ) -> wasmtime::Result<()>62*112112d4SAlex Crichton     async fn when_ready<T>(
63*112112d4SAlex Crichton         accessor: &Accessor<T, Self>,
64*112112d4SAlex Crichton         thing: Resource<Thing>,
65*112112d4SAlex Crichton     ) -> wasmtime::Result<()> {
66*112112d4SAlex Crichton         let wakers = accessor.with(|mut view| {
67*112112d4SAlex Crichton             Ok::<_, wasmtime::Error>(view.get().table.get(&thing)?.wakers.clone())
68*112112d4SAlex Crichton         })?;
69*112112d4SAlex Crichton 
70*112112d4SAlex Crichton         future::poll_fn(move |cx| {
71*112112d4SAlex Crichton             let mut wakers = wakers.lock().unwrap();
72*112112d4SAlex Crichton             if let Some(wakers) = wakers.deref_mut() {
73*112112d4SAlex Crichton                 wakers.push(cx.waker().clone());
74*112112d4SAlex Crichton                 Poll::Pending
75*112112d4SAlex Crichton             } else {
76*112112d4SAlex Crichton                 Poll::Ready(())
77*112112d4SAlex Crichton             }
78*112112d4SAlex Crichton         })
79*112112d4SAlex Crichton         .await;
80*112112d4SAlex Crichton 
81*112112d4SAlex Crichton         Ok(())
82*112112d4SAlex Crichton     }
83*112112d4SAlex Crichton }
84*112112d4SAlex Crichton 
85*112112d4SAlex Crichton impl bindings::local::local::ready::Host for Ctx {}
86