Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/test-programs/src/bin/async_poll_stackless.rs
1693 views
1
#![expect(unsafe_op_in_unsafe_fn, reason = "old code, not worth updating yet")]
2
3
mod bindings {
4
wit_bindgen::generate!({
5
path: "../misc/component-async-tests/wit",
6
world: "poll",
7
});
8
}
9
10
use {
11
bindings::local::local::ready,
12
test_programs::async_::{
13
CALLBACK_CODE_EXIT, CALLBACK_CODE_POLL, EVENT_NONE, EVENT_SUBTASK, STATUS_RETURNED,
14
context_get, context_set, subtask_drop, waitable_join, waitable_set_drop, waitable_set_new,
15
},
16
};
17
18
#[cfg(target_arch = "wasm32")]
19
#[link(wasm_import_module = "[export]local:local/run")]
20
unsafe extern "C" {
21
#[link_name = "[task-return][async]run"]
22
fn task_return_run();
23
}
24
#[cfg(not(target_arch = "wasm32"))]
25
unsafe extern "C" fn task_return_run() {
26
unreachable!()
27
}
28
29
fn async_when_ready() -> u32 {
30
#[cfg(not(target_arch = "wasm32"))]
31
{
32
unreachable!()
33
}
34
35
#[cfg(target_arch = "wasm32")]
36
{
37
#[link(wasm_import_module = "local:local/ready")]
38
unsafe extern "C" {
39
#[link_name = "[async-lower][async]when-ready"]
40
fn call_when_ready() -> u32;
41
}
42
unsafe { call_when_ready() }
43
}
44
}
45
46
enum State {
47
S0,
48
S1 { set: u32 },
49
S2 { set: u32, call: u32 },
50
S3 { set: u32, call: u32 },
51
S4 { set: u32 },
52
S5 { set: u32 },
53
}
54
55
#[unsafe(export_name = "[async-lift]local:local/run#[async]run")]
56
unsafe extern "C" fn export_run() -> u32 {
57
context_set(u32::try_from(Box::into_raw(Box::new(State::S0)) as usize).unwrap());
58
callback_run(EVENT_NONE, 0, 0)
59
}
60
61
#[unsafe(export_name = "[callback][async-lift]local:local/run#[async]run")]
62
unsafe extern "C" fn callback_run(event0: u32, event1: u32, event2: u32) -> u32 {
63
let state = &mut *(usize::try_from(context_get()).unwrap() as *mut State);
64
match state {
65
State::S0 => {
66
assert_eq!(event0, EVENT_NONE);
67
68
ready::set_ready(false);
69
70
let set = waitable_set_new();
71
72
*state = State::S1 { set };
73
74
CALLBACK_CODE_POLL | (set << 4)
75
}
76
77
State::S1 { set } => {
78
assert_eq!(event0, EVENT_NONE);
79
80
let set = *set;
81
let result = async_when_ready();
82
let status = result & 0xf;
83
let call = result >> 4;
84
assert!(status != STATUS_RETURNED);
85
waitable_join(call, set);
86
87
*state = State::S2 { set, call };
88
89
CALLBACK_CODE_POLL | (set << 4)
90
}
91
92
State::S2 { set, call } => {
93
assert_eq!(event0, EVENT_NONE);
94
95
let set = *set;
96
let call = *call;
97
ready::set_ready(true);
98
99
*state = State::S3 { set, call };
100
101
CALLBACK_CODE_POLL | (set << 4)
102
}
103
104
State::S3 { set, call } => {
105
let set = *set;
106
107
if event0 != EVENT_NONE {
108
assert_eq!(event0, EVENT_SUBTASK);
109
assert_eq!(event1, *call);
110
assert_eq!(event2, STATUS_RETURNED);
111
112
subtask_drop(*call);
113
114
*state = State::S4 { set };
115
}
116
117
CALLBACK_CODE_POLL | (set << 4)
118
}
119
120
State::S4 { set } => {
121
assert_eq!(event0, EVENT_NONE);
122
123
let set = *set;
124
assert_eq!(async_when_ready(), STATUS_RETURNED);
125
126
*state = State::S5 { set };
127
128
CALLBACK_CODE_POLL | (set << 4)
129
}
130
131
State::S5 { set } => {
132
assert_eq!(event0, EVENT_NONE);
133
134
waitable_set_drop(*set);
135
136
drop(Box::from_raw(state));
137
138
context_set(0);
139
140
task_return_run();
141
142
CALLBACK_CODE_EXIT
143
}
144
}
145
}
146
147
// Unused function; required since this file is built as a `bin`:
148
fn main() {}
149
150