Path: blob/main/crates/test-programs/src/bin/async_cancel_callee.rs
3073 views
mod bindings {1wit_bindgen::generate!({2path: "../misc/component-async-tests/wit",3world: "cancel-callee",4});5}67use test_programs::async_::{8CALLBACK_CODE_EXIT, CALLBACK_CODE_WAIT, EVENT_CANCELLED, EVENT_NONE, EVENT_SUBTASK,9STATUS_RETURN_CANCELLED, STATUS_RETURNED, STATUS_STARTED, context_get, context_set,10subtask_cancel, subtask_drop, task_cancel, waitable_join, waitable_set_drop, waitable_set_new,11};1213#[cfg(target_arch = "wasm32")]14#[link(wasm_import_module = "[export]local:local/sleep-with-options")]15unsafe extern "C" {16#[link_name = "[task-return]sleep-millis"]17fn task_return_sleep_millis();18}19#[cfg(not(target_arch = "wasm32"))]20unsafe extern "C" fn task_return_sleep_millis() {21unreachable!()22}2324#[cfg(target_arch = "wasm32")]25#[link(wasm_import_module = "local:local/sleep")]26unsafe extern "C" {27#[link_name = "sleep-millis"]28fn sleep_millis(_: u64);29}30#[cfg(not(target_arch = "wasm32"))]31unsafe fn sleep_millis(_: u64) {32unreachable!()33}3435#[cfg(target_arch = "wasm32")]36#[link(wasm_import_module = "local:local/sleep")]37unsafe extern "C" {38#[link_name = "[async-lower]sleep-millis"]39fn sleep_millis_async(ms: u64) -> u32;40}41#[cfg(not(target_arch = "wasm32"))]42unsafe fn sleep_millis_async(_ms: u64) -> u32 {43unreachable!()44}4546const ON_CANCEL_TASK_RETURN: u8 = 0;47const ON_CANCEL_TASK_CANCEL: u8 = 1;4849const _MODE_NORMAL: u8 = 0;50const _MODE_TRAP_CANCEL_GUEST_AFTER_START_CANCELLED: u8 = 1;51const _MODE_TRAP_CANCEL_GUEST_AFTER_RETURN_CANCELLED: u8 = 2;52const _MODE_TRAP_CANCEL_GUEST_AFTER_RETURN: u8 = 3;53const MODE_TRAP_CANCEL_HOST_AFTER_RETURN_CANCELLED: u8 = 4;54const MODE_TRAP_CANCEL_HOST_AFTER_RETURN: u8 = 5;55const MODE_LEAK_TASK_AFTER_CANCEL: u8 = 6;5657#[derive(Clone, Copy)]58struct SleepParams {59time_in_millis: u64,60on_cancel: u8,61on_cancel_delay_millis: u64,62synchronous_delay: bool,63mode: u8,64}6566enum State {67S0(SleepParams),68S1 {69set: u32,70waitable: u32,71params: SleepParams,72},73S2 {74set: u32,75waitable: u32,76params: SleepParams,77},78}7980#[unsafe(export_name = "local:local/backpressure#set-backpressure")]81unsafe extern "C" fn export_set_backpressure(enabled: bool) {82if enabled {83wit_bindgen::backpressure_inc();84} else {85wit_bindgen::backpressure_dec();86}87}8889#[unsafe(export_name = "local:local/backpressure#inc-backpressure")]90unsafe extern "C" fn export_inc_backpressure() {91wit_bindgen::backpressure_inc();92}9394#[unsafe(export_name = "local:local/backpressure#dec-backpressure")]95unsafe extern "C" fn export_dec_backpressure() {96wit_bindgen::backpressure_dec();97}9899#[unsafe(export_name = "local:local/sleep#sleep-millis")]100unsafe extern "C" fn export_sleep_sleep_millis(time_in_millis: u64) {101unsafe {102sleep_millis(time_in_millis);103}104}105106#[unsafe(export_name = "[async-lift]local:local/sleep-with-options#sleep-millis")]107unsafe extern "C" fn export_sleep_with_options_sleep_millis(108time_in_millis: u64,109on_cancel: u8,110on_cancel_delay_millis: u64,111synchronous_delay: bool,112mode: u8,113) -> u32 {114unsafe {115context_set(116u32::try_from(Box::into_raw(Box::new(State::S0(SleepParams {117time_in_millis,118on_cancel,119on_cancel_delay_millis,120synchronous_delay,121mode,122}))) as usize)123.unwrap(),124);125callback_sleep_with_options_sleep_millis(EVENT_NONE, 0, 0)126}127}128129#[unsafe(export_name = "[callback][async-lift]local:local/sleep-with-options#sleep-millis")]130unsafe extern "C" fn callback_sleep_with_options_sleep_millis(131event0: u32,132event1: u32,133event2: u32,134) -> u32 {135unsafe {136let state = &mut *(usize::try_from(context_get()).unwrap() as *mut State);137match state {138State::S0(params) => {139assert_eq!(event0, EVENT_NONE);140141let status = sleep_millis_async(params.time_in_millis);142143let waitable = status >> 4;144let status = status & 0xF;145146assert_eq!(status, STATUS_STARTED);147148let set = waitable_set_new();149waitable_join(waitable, set);150151*state = State::S1 {152set,153waitable,154params: *params,155};156157CALLBACK_CODE_WAIT | (set << 4)158}159160State::S1 {161set,162waitable,163params,164} => {165assert_eq!(event0, EVENT_CANCELLED);166167let result = subtask_cancel(*waitable);168169assert_eq!(result, STATUS_RETURN_CANCELLED);170171if params.mode == MODE_TRAP_CANCEL_HOST_AFTER_RETURN_CANCELLED {172// This should trap, since `waitable` has already been173// cancelled:174subtask_cancel(*waitable);175unreachable!()176}177178waitable_join(*waitable, 0);179180if params.mode != MODE_LEAK_TASK_AFTER_CANCEL {181subtask_drop(*waitable);182}183184if params.on_cancel_delay_millis == 0 {185match params.on_cancel {186ON_CANCEL_TASK_RETURN => task_return_sleep_millis(),187ON_CANCEL_TASK_CANCEL => task_cancel(),188_ => unreachable!(),189}190191CALLBACK_CODE_EXIT192} else if params.synchronous_delay {193sleep_millis(params.on_cancel_delay_millis);194195match params.on_cancel {196ON_CANCEL_TASK_RETURN => task_return_sleep_millis(),197ON_CANCEL_TASK_CANCEL => task_cancel(),198_ => unreachable!(),199}200201CALLBACK_CODE_EXIT202} else {203let status = sleep_millis_async(params.on_cancel_delay_millis);204205let waitable = status >> 4;206let status = status & 0xF;207208assert_eq!(status, STATUS_STARTED);209210waitable_join(waitable, *set);211212let set = *set;213214*state = State::S2 {215set,216waitable,217params: *params,218};219220CALLBACK_CODE_WAIT | (set << 4)221}222}223224State::S2 {225set,226waitable,227params,228} => {229assert_eq!(event0, EVENT_SUBTASK);230assert_eq!(event1, *waitable);231assert_eq!(event2, STATUS_RETURNED);232233if params.mode == MODE_TRAP_CANCEL_HOST_AFTER_RETURN {234// This should trap, since `waitable` has already returned:235subtask_cancel(*waitable);236unreachable!()237}238239waitable_join(*waitable, 0);240subtask_drop(*waitable);241waitable_set_drop(*set);242243match params.on_cancel {244ON_CANCEL_TASK_RETURN => task_return_sleep_millis(),245ON_CANCEL_TASK_CANCEL => task_cancel(),246_ => unreachable!(),247}248249CALLBACK_CODE_EXIT250}251}252}253}254255// Unused function; required since this file is built as a `bin`:256fn main() {}257258259