wit-bindgen
Advanced tools
| { | ||
| "git": { | ||
| "sha1": "65ee50585900d9de30d48e99d03ff3e3f97ae186" | ||
| "sha1": "875e8632bb4b45d6b6ea1e3a72c66354c86d5d29" | ||
| }, | ||
| "path_in_vcs": "crates/guest-rust" | ||
| } |
+17
-17
@@ -318,5 +318,5 @@ # This file is automatically @generated by Cargo. | ||
| name = "wasm-encoder" | ||
| version = "0.240.0" | ||
| version = "0.241.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "06d642d8c5ecc083aafe9ceb32809276a304547a3a6eeecceb5d8152598bc71f" | ||
| checksum = "e01164c9dda68301e34fdae536c23ed6fe90ce6d97213ccc171eebbd3d02d6b8" | ||
| dependencies = [ | ||
@@ -329,5 +329,5 @@ "leb128fmt", | ||
| name = "wasm-metadata" | ||
| version = "0.240.0" | ||
| version = "0.241.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "ee093e1e1ccffa005b9b778f7a10ccfd58e25a20eccad294a1a93168d076befb" | ||
| checksum = "876fe286f2fa416386deedebe8407e6f19e0b5aeaef3d03161e77a15fa80f167" | ||
| dependencies = [ | ||
@@ -342,5 +342,5 @@ "anyhow", | ||
| name = "wasmparser" | ||
| version = "0.240.0" | ||
| version = "0.241.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "b722dcf61e0ea47440b53ff83ccb5df8efec57a69d150e4f24882e4eba7e24a4" | ||
| checksum = "46d90019b1afd4b808c263e428de644f3003691f243387d30d673211ee0cb8e8" | ||
| dependencies = [ | ||
@@ -355,3 +355,3 @@ "bitflags", | ||
| name = "wit-bindgen" | ||
| version = "0.47.0" | ||
| version = "0.48.0" | ||
| dependencies = [ | ||
@@ -367,5 +367,5 @@ "bitflags", | ||
| name = "wit-bindgen-core" | ||
| version = "0.47.0" | ||
| version = "0.48.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "cdf62e62178415a705bda25dc01c54ed65c0f956e4efd00ca89447a9a84f4881" | ||
| checksum = "a64f7435c8448e456bc6e8f14e27ee4f65926cbdfe72b7bf95badeae2501bacf" | ||
| dependencies = [ | ||
@@ -379,5 +379,5 @@ "anyhow", | ||
| name = "wit-bindgen-rust" | ||
| version = "0.47.0" | ||
| version = "0.48.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "c6d585319871ca18805056f69ddec7541770fc855820f9944029cb2b75ea108f" | ||
| checksum = "612651c001e0de8bfb7138af5551f80461f25caa627b64d7014a80914cf4f407" | ||
| dependencies = [ | ||
@@ -396,5 +396,5 @@ "anyhow", | ||
| name = "wit-bindgen-rust-macro" | ||
| version = "0.47.0" | ||
| version = "0.48.0" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "bde589435d322e88b8f708f70e313f60dfb7975ac4e7c623fef6f1e5685d90e8" | ||
| checksum = "16c64812d84284d45ce7d7371dc9eb0bcda2f0f747128bd1b4dae1e08217bad3" | ||
| dependencies = [ | ||
@@ -412,5 +412,5 @@ "anyhow", | ||
| name = "wit-component" | ||
| version = "0.240.0" | ||
| version = "0.241.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "7dc5474b078addc5fe8a72736de8da3acfb3ff324c2491133f8b59594afa1a20" | ||
| checksum = "1fd0c57df25e7ee612d946d3b7646c1ddb2310f8280aa2c17e543b66e0812241" | ||
| dependencies = [ | ||
@@ -432,5 +432,5 @@ "anyhow", | ||
| name = "wit-parser" | ||
| version = "0.240.0" | ||
| version = "0.241.2" | ||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| checksum = "9875ea3fa272f57cc1fc50f225a7b94021a7878c484b33792bccad0d93223439" | ||
| checksum = "09ef1c6ad67f35c831abd4039c02894de97034100899614d1c44e2268ad01c91" | ||
| dependencies = [ | ||
@@ -437,0 +437,0 @@ "anyhow", |
+3
-4
@@ -16,3 +16,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "wit-bindgen" | ||
| version = "0.47.0" | ||
| version = "0.48.0" | ||
| authors = ["Alex Crichton <alex@alexcrichton.com>"] | ||
@@ -39,5 +39,4 @@ build = "build.rs" | ||
| async = [ | ||
| "macros", | ||
| "std", | ||
| "wit-bindgen-rust-macro/async", | ||
| "wit-bindgen-rust-macro?/async", | ||
| ] | ||
@@ -87,3 +86,3 @@ async-spawn = [ | ||
| [dependencies.wit-bindgen-rust-macro] | ||
| version = "0.47.0" | ||
| version = "0.48.0" | ||
| optional = true |
@@ -121,2 +121,3 @@ //! Runtime support for `future<T>` in the component model. | ||
| use std::marker; | ||
| use std::mem::{self, ManuallyDrop}; | ||
| use std::pin::Pin; | ||
@@ -128,2 +129,35 @@ use std::ptr; | ||
| /// Helper trait which encapsulates the various operations which can happen | ||
| /// with a future. | ||
| pub trait FutureOps { | ||
| /// The Rust type that's sent or received on this future. | ||
| type Payload; | ||
| /// The `future.new` intrinsic. | ||
| fn new(&mut self) -> u64; | ||
| /// The canonical ABI layout of the type that this future is | ||
| /// sending/receiving. | ||
| fn elem_layout(&mut self) -> Layout; | ||
| /// Converts a Rust type to its canonical ABI representation. | ||
| unsafe fn lower(&mut self, payload: Self::Payload, dst: *mut u8); | ||
| /// Used to deallocate any Rust-owned lists in the canonical ABI | ||
| /// representation for when a value is successfully sent but needs to be | ||
| /// cleaned up. | ||
| unsafe fn dealloc_lists(&mut self, dst: *mut u8); | ||
| /// Converts from the canonical ABI representation to a Rust value. | ||
| unsafe fn lift(&mut self, dst: *mut u8) -> Self::Payload; | ||
| /// The `future.write` intrinsic | ||
| unsafe fn start_write(&mut self, future: u32, val: *const u8) -> u32; | ||
| /// The `future.read` intrinsic | ||
| unsafe fn start_read(&mut self, future: u32, val: *mut u8) -> u32; | ||
| /// The `future.cancel-read` intrinsic | ||
| unsafe fn cancel_read(&mut self, future: u32) -> u32; | ||
| /// The `future.cancel-write` intrinsic | ||
| unsafe fn cancel_write(&mut self, future: u32) -> u32; | ||
| /// The `future.drop-readable` intrinsic | ||
| unsafe fn drop_readable(&mut self, future: u32); | ||
| /// The `future.drop-writable` intrinsic | ||
| unsafe fn drop_writable(&mut self, future: u32); | ||
| } | ||
| /// Function table used for [`FutureWriter`] and [`FutureReader`] | ||
@@ -180,2 +214,40 @@ /// | ||
| impl<T> FutureOps for &'static FutureVtable<T> { | ||
| type Payload = T; | ||
| fn new(&mut self) -> u64 { | ||
| unsafe { (self.new)() } | ||
| } | ||
| fn elem_layout(&mut self) -> Layout { | ||
| self.layout | ||
| } | ||
| unsafe fn lower(&mut self, payload: Self::Payload, dst: *mut u8) { | ||
| (self.lower)(payload, dst) | ||
| } | ||
| unsafe fn dealloc_lists(&mut self, dst: *mut u8) { | ||
| (self.dealloc_lists)(dst) | ||
| } | ||
| unsafe fn lift(&mut self, dst: *mut u8) -> Self::Payload { | ||
| (self.lift)(dst) | ||
| } | ||
| unsafe fn start_write(&mut self, future: u32, val: *const u8) -> u32 { | ||
| (self.start_write)(future, val) | ||
| } | ||
| unsafe fn start_read(&mut self, future: u32, val: *mut u8) -> u32 { | ||
| (self.start_read)(future, val) | ||
| } | ||
| unsafe fn cancel_read(&mut self, future: u32) -> u32 { | ||
| (self.cancel_read)(future) | ||
| } | ||
| unsafe fn cancel_write(&mut self, future: u32) -> u32 { | ||
| (self.cancel_write)(future) | ||
| } | ||
| unsafe fn drop_readable(&mut self, future: u32) { | ||
| (self.drop_readable)(future) | ||
| } | ||
| unsafe fn drop_writable(&mut self, future: u32) { | ||
| (self.drop_writable)(future) | ||
| } | ||
| } | ||
| /// Helper function to create a new read/write pair for a component model | ||
@@ -192,4 +264,19 @@ /// future. | ||
| ) -> (FutureWriter<T>, FutureReader<T>) { | ||
| let (tx, rx) = unsafe { raw_future_new(vtable) }; | ||
| (FutureWriter::new(tx, default), rx) | ||
| } | ||
| /// Helper function to create a new read/write pair for a component model | ||
| /// future. | ||
| /// | ||
| /// # Unsafety | ||
| /// | ||
| /// This function is unsafe as it requires the functions within `vtable` to | ||
| /// correctly uphold the contracts of the component model. | ||
| pub unsafe fn raw_future_new<O>(mut ops: O) -> (RawFutureWriter<O>, RawFutureReader<O>) | ||
| where | ||
| O: FutureOps + Clone, | ||
| { | ||
| unsafe { | ||
| let handles = (vtable.new)(); | ||
| let handles = ops.new(); | ||
| let reader = handles as u32; | ||
@@ -199,4 +286,4 @@ let writer = (handles >> 32) as u32; | ||
| ( | ||
| FutureWriter::new(writer, default, vtable), | ||
| FutureReader::new(reader, vtable), | ||
| RawFutureWriter::new(writer, ops.clone()), | ||
| RawFutureReader::new(reader, ops), | ||
| ) | ||
@@ -211,4 +298,3 @@ } | ||
| pub struct FutureWriter<T: 'static> { | ||
| handle: u32, | ||
| vtable: &'static FutureVtable<T>, | ||
| raw: ManuallyDrop<RawFutureWriter<&'static FutureVtable<T>>>, | ||
@@ -236,9 +322,7 @@ /// Whether or not a value should be written during `drop`. | ||
| /// correctly uphold the contracts of the component model. | ||
| #[doc(hidden)] | ||
| pub unsafe fn new(handle: u32, default: fn() -> T, vtable: &'static FutureVtable<T>) -> Self { | ||
| unsafe fn new(raw: RawFutureWriter<&'static FutureVtable<T>>, default: fn() -> T) -> Self { | ||
| Self { | ||
| handle, | ||
| raw: ManuallyDrop::new(raw), | ||
| default, | ||
| should_write_default_value: true, | ||
| vtable, | ||
| } | ||
@@ -274,6 +358,7 @@ } | ||
| /// In such a situation the operation can be retried at a future date. | ||
| pub fn write(self, value: T) -> FutureWrite<T> { | ||
| FutureWrite { | ||
| op: WaitableOperation::new(FutureWriteOp(marker::PhantomData), (self, value)), | ||
| } | ||
| pub fn write(mut self, value: T) -> FutureWrite<T> { | ||
| let raw = unsafe { ManuallyDrop::take(&mut self.raw).write(value) }; | ||
| let default = self.default; | ||
| mem::forget(self); | ||
| FutureWrite { raw, default } | ||
| } | ||
@@ -285,3 +370,3 @@ } | ||
| f.debug_struct("FutureWriter") | ||
| .field("handle", &self.handle) | ||
| .field("handle", &self.raw.handle) | ||
| .finish() | ||
@@ -294,26 +379,14 @@ } | ||
| // If a value has not yet been written into this writer than that must | ||
| // be done so now. Perform a "clone" of `self` ensuring that | ||
| // `should_write_default_value` is set to `false` to avoid infinite | ||
| // loops by accident. The cloned `FutureWriter` will be responsible for | ||
| // performing the `drop-writable` call below once the write has | ||
| // completed. | ||
| // be done so now. Take the `raw` writer and perform the write via a | ||
| // waker that drives the future. | ||
| // | ||
| // Note, though, that if `should_write_default_value` is `false` then a | ||
| // write has already happened and we can go ahead and just synchronously | ||
| // drop this writer as we would any other handle. | ||
| // If `should_write_default_value` is `false` then a write has already | ||
| // happened and we can go ahead and just synchronously drop this writer | ||
| // as we would any other handle. | ||
| if self.should_write_default_value { | ||
| let clone = FutureWriter { | ||
| handle: self.handle, | ||
| default: self.default, | ||
| should_write_default_value: false, | ||
| vtable: self.vtable, | ||
| }; | ||
| let value = (clone.default)(); | ||
| let write = clone.write(value); | ||
| Arc::new(DeferredWrite::new(write)).wake(); | ||
| let raw = unsafe { ManuallyDrop::take(&mut self.raw) }; | ||
| let value = (self.default)(); | ||
| raw.write_and_forget(value); | ||
| } else { | ||
| unsafe { | ||
| rtdebug!("future.drop-writable({})", self.handle); | ||
| (self.vtable.drop_writable)(self.handle); | ||
| } | ||
| unsafe { ManuallyDrop::drop(&mut self.raw) } | ||
| } | ||
@@ -323,27 +396,69 @@ } | ||
| /// Helper structure which behaves both as a future of sorts and an executor of | ||
| /// sorts. | ||
| /// Represents a write operation which may be cancelled prior to completion. | ||
| /// | ||
| /// This type is constructed in `Drop for FutureWriter<T>` to send out a | ||
| /// default value when no other has been written. This manages the | ||
| /// `FutureWrite` operation happening internally through a `Wake` | ||
| /// implementation. That means that this is a sort of cyclical future which, | ||
| /// when woken, will complete the write operation. | ||
| /// | ||
| /// The purpose of this is to be a "lightweight" way of "spawn"-ing a future | ||
| /// write to happen in the background. Crucially, however, this doesn't require | ||
| /// the `async-spawn` feature and instead works with the `wasip3_task` C ABI | ||
| /// structures (which spawn doesn't support). | ||
| struct DeferredWrite<T: 'static> { | ||
| write: Mutex<FutureWrite<T>>, | ||
| /// This is returned by [`FutureWriter::write`]. | ||
| pub struct FutureWrite<T: 'static> { | ||
| raw: RawFutureWrite<&'static FutureVtable<T>>, | ||
| default: fn() -> T, | ||
| } | ||
| // TODO | ||
| unsafe impl<T> Send for DeferredWrite<T> {} | ||
| unsafe impl<T> Sync for DeferredWrite<T> {} | ||
| /// Result of [`FutureWrite::cancel`]. | ||
| #[derive(Debug)] | ||
| pub enum FutureWriteCancel<T: 'static> { | ||
| /// The cancel request raced with the receipt of the sent value, and the | ||
| /// value was actually sent. Neither the value nor the writer are made | ||
| /// available here as both are gone. | ||
| AlreadySent, | ||
| impl<T> DeferredWrite<T> { | ||
| fn new(write: FutureWrite<T>) -> DeferredWrite<T> { | ||
| DeferredWrite { | ||
| write: Mutex::new(write), | ||
| /// The other end was dropped before cancellation happened. | ||
| /// | ||
| /// In this case the original value is returned back to the caller but the | ||
| /// writer itself is not longer accessible as it's no longer usable. | ||
| Dropped(T), | ||
| /// The pending write was successfully cancelled and the value being written | ||
| /// is returned along with the writer to resume again in the future if | ||
| /// necessary. | ||
| Cancelled(T, FutureWriter<T>), | ||
| } | ||
| impl<T: 'static> Future for FutureWrite<T> { | ||
| type Output = Result<(), FutureWriteError<T>>; | ||
| fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| self.pin_project().poll(cx) | ||
| } | ||
| } | ||
| impl<T: 'static> FutureWrite<T> { | ||
| fn pin_project(self: Pin<&mut Self>) -> Pin<&mut RawFutureWrite<&'static FutureVtable<T>>> { | ||
| // SAFETY: we've chosen that when `Self` is pinned that it translates to | ||
| // always pinning the inner field, so that's codified here. | ||
| unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().raw) } | ||
| } | ||
| /// Cancel this write if it hasn't already completed. | ||
| /// | ||
| /// This method can be used to cancel a write-in-progress and re-acquire | ||
| /// the writer and the value being sent. Note that the write operation may | ||
| /// succeed racily or the other end may also drop racily, and these | ||
| /// outcomes are reflected in the returned value here. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// Panics if the operation has already been completed via `Future::poll`, | ||
| /// or if this method is called twice. | ||
| pub fn cancel(self: Pin<&mut Self>) -> FutureWriteCancel<T> { | ||
| let default = self.default; | ||
| match self.pin_project().cancel() { | ||
| RawFutureWriteCancel::AlreadySent => FutureWriteCancel::AlreadySent, | ||
| RawFutureWriteCancel::Dropped(val) => FutureWriteCancel::Dropped(val), | ||
| RawFutureWriteCancel::Cancelled(val, raw) => FutureWriteCancel::Cancelled( | ||
| val, | ||
| FutureWriter { | ||
| raw: ManuallyDrop::new(raw), | ||
| default, | ||
| should_write_default_value: true, | ||
| }, | ||
| ), | ||
| } | ||
@@ -353,42 +468,137 @@ } | ||
| impl<T> Wake for DeferredWrite<T> { | ||
| fn wake(self: Arc<Self>) { | ||
| // When a `wake` signal comes in that should happen in two locations: | ||
| impl<T: 'static> Drop for FutureWrite<T> { | ||
| fn drop(&mut self) { | ||
| if self.raw.op.is_done() { | ||
| return; | ||
| } | ||
| // Although the underlying `WaitableOperation` will already | ||
| // auto-cancel-on-drop we need to specially handle that here because if | ||
| // the cancellation goes through then it means that no value will have | ||
| // been written to this future which will cause a trap. By using | ||
| // `Self::cancel` it's ensured that if cancellation succeeds a | ||
| // `FutureWriter` is created. In `Drop for FutureWriter` that'll handle | ||
| // the last-ditch write-default logic. | ||
| // | ||
| // 1. When `DeferredWrite` is initially constructed. | ||
| // 2. When an event comes in indicating that the internal write has | ||
| // completed. | ||
| // | ||
| // The implementation here is the same in both cases. A clone of `self` | ||
| // is converted to a `Waker`, and this `Waker` notably owns the | ||
| // internal future itself. The internal write operation is then pushed | ||
| // forward (e.g. it's issued in (1) or checked up on in (2)). | ||
| // | ||
| // If `Pending` is returned then `waker` should have been stored away | ||
| // within the `wasip3_task` C ABI structure. Otherwise it should not | ||
| // have been stored away and `self` should be the sole reference which | ||
| // means everything will get cleaned up when this function returns. | ||
| let poll = { | ||
| let waker = Waker::from(self.clone()); | ||
| let mut cx = Context::from_waker(&waker); | ||
| let mut write = self.write.lock().unwrap(); | ||
| unsafe { Pin::new_unchecked(&mut *write).poll(&mut cx) } | ||
| }; | ||
| if poll.is_ready() { | ||
| assert_eq!(Arc::strong_count(&self), 1); | ||
| } else { | ||
| assert!(Arc::strong_count(&self) > 1); | ||
| // SAFETY: we're in the destructor here so the value `self` is about | ||
| // to go away and we can guarantee we're not moving out of it. | ||
| let pin = unsafe { Pin::new_unchecked(self) }; | ||
| pin.cancel(); | ||
| } | ||
| } | ||
| /// Raw version of [`FutureWriter`]. | ||
| pub struct RawFutureWriter<O: FutureOps> { | ||
| handle: u32, | ||
| ops: O, | ||
| } | ||
| impl<O: FutureOps> RawFutureWriter<O> { | ||
| unsafe fn new(handle: u32, ops: O) -> Self { | ||
| Self { handle, ops } | ||
| } | ||
| /// Same as [`FutureWriter::write`], but the raw version. | ||
| pub fn write(self, value: O::Payload) -> RawFutureWrite<O> { | ||
| RawFutureWrite { | ||
| op: WaitableOperation::new(FutureWriteOp(marker::PhantomData), (self, value)), | ||
| } | ||
| assert_eq!(Arc::weak_count(&self), 0); | ||
| } | ||
| /// Writes `value` in the background. | ||
| /// | ||
| /// This does not block and is not cancellable. | ||
| pub fn write_and_forget(self, value: O::Payload) | ||
| where | ||
| O: 'static, | ||
| { | ||
| return Arc::new(DeferredWrite { | ||
| write: Mutex::new(self.write(value)), | ||
| }) | ||
| .wake(); | ||
| /// Helper structure which behaves both as a future of sorts and an | ||
| /// executor of sorts. | ||
| /// | ||
| /// This type is constructed in `Drop for FutureWriter<T>` to send out a | ||
| /// default value when no other has been written. This manages the | ||
| /// `FutureWrite` operation happening internally through a `Wake` | ||
| /// implementation. That means that this is a sort of cyclical future | ||
| /// which, when woken, will complete the write operation. | ||
| /// | ||
| /// The purpose of this is to be a "lightweight" way of "spawn"-ing a | ||
| /// future write to happen in the background. Crucially, however, this | ||
| /// doesn't require the `async-spawn` feature and instead works with the | ||
| /// `wasip3_task` C ABI structures (which spawn doesn't support). | ||
| struct DeferredWrite<O: FutureOps> { | ||
| write: Mutex<RawFutureWrite<O>>, | ||
| } | ||
| // SAFETY: Needed to satisfy `Waker::from` but otherwise should be ok | ||
| // because wasm doesn't have threads anyway right now. | ||
| unsafe impl<O: FutureOps> Send for DeferredWrite<O> {} | ||
| unsafe impl<O: FutureOps> Sync for DeferredWrite<O> {} | ||
| impl<O: FutureOps + 'static> Wake for DeferredWrite<O> { | ||
| fn wake(self: Arc<Self>) { | ||
| // When a `wake` signal comes in that should happen in two | ||
| // locations: | ||
| // | ||
| // 1. When `DeferredWrite` is initially constructed. | ||
| // 2. When an event comes in indicating that the internal write | ||
| // has completed. | ||
| // | ||
| // The implementation here is the same in both cases. A clone of | ||
| // `self` is converted to a `Waker`, and this `Waker` notably | ||
| // owns the internal future itself. The internal write operation | ||
| // is then pushed forward (e.g. it's issued in (1) or checked up | ||
| // on in (2)). | ||
| // | ||
| // If `Pending` is returned then `waker` should have been stored | ||
| // away within the `wasip3_task` C ABI structure. Otherwise it | ||
| // should not have been stored away and `self` should be the | ||
| // sole reference which means everything will get cleaned up | ||
| // when this function returns. | ||
| let poll = { | ||
| let waker = Waker::from(self.clone()); | ||
| let mut cx = Context::from_waker(&waker); | ||
| let mut write = self.write.lock().unwrap(); | ||
| unsafe { Pin::new_unchecked(&mut *write).poll(&mut cx) } | ||
| }; | ||
| if poll.is_ready() { | ||
| assert_eq!(Arc::strong_count(&self), 1); | ||
| } else { | ||
| assert!(Arc::strong_count(&self) > 1); | ||
| } | ||
| assert_eq!(Arc::weak_count(&self), 0); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| impl<O: FutureOps> fmt::Debug for RawFutureWriter<O> { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| f.debug_struct("RawFutureWriter") | ||
| .field("handle", &self.handle) | ||
| .finish() | ||
| } | ||
| } | ||
| impl<O: FutureOps> Drop for RawFutureWriter<O> { | ||
| fn drop(&mut self) { | ||
| unsafe { | ||
| rtdebug!("future.drop-writable({})", self.handle); | ||
| self.ops.drop_writable(self.handle); | ||
| } | ||
| } | ||
| } | ||
| /// Represents a write operation which may be cancelled prior to completion. | ||
| /// | ||
| /// This is returned by [`FutureWriter::write`]. | ||
| pub struct FutureWrite<T: 'static> { | ||
| op: WaitableOperation<FutureWriteOp<T>>, | ||
| pub struct RawFutureWrite<O: FutureOps> { | ||
| op: WaitableOperation<FutureWriteOp<O>>, | ||
| } | ||
| struct FutureWriteOp<T>(marker::PhantomData<T>); | ||
| struct FutureWriteOp<O>(marker::PhantomData<O>); | ||
@@ -401,12 +611,9 @@ enum WriteComplete<T> { | ||
| unsafe impl<T> WaitableOp for FutureWriteOp<T> | ||
| where | ||
| T: 'static, | ||
| { | ||
| type Start = (FutureWriter<T>, T); | ||
| type InProgress = (FutureWriter<T>, Option<Cleanup>); | ||
| type Result = (WriteComplete<T>, FutureWriter<T>); | ||
| type Cancel = FutureWriteCancel<T>; | ||
| unsafe impl<O: FutureOps> WaitableOp for FutureWriteOp<O> { | ||
| type Start = (RawFutureWriter<O>, O::Payload); | ||
| type InProgress = (RawFutureWriter<O>, Option<Cleanup>); | ||
| type Result = (WriteComplete<O::Payload>, RawFutureWriter<O>); | ||
| type Cancel = RawFutureWriteCancel<O>; | ||
| fn start(&self, (writer, value): Self::Start) -> (u32, Self::InProgress) { | ||
| fn start(&mut self, (mut writer, value): Self::Start) -> (u32, Self::InProgress) { | ||
| // TODO: it should be safe to store the lower-destination in | ||
@@ -422,8 +629,8 @@ // `WaitableOperation` using `Pin` memory and such, but that would | ||
| // pointer to initialize it. | ||
| let (ptr, cleanup) = Cleanup::new(writer.vtable.layout); | ||
| // SAFETY: `ptr` is allocated with `vtable.layout` and should be | ||
| let (ptr, cleanup) = Cleanup::new(writer.ops.elem_layout()); | ||
| // SAFETY: `ptr` is allocated with `ops.layout` and should be | ||
| // safe to use here. | ||
| let code = unsafe { | ||
| (writer.vtable.lower)(value, ptr); | ||
| (writer.vtable.start_write)(writer.handle, ptr) | ||
| writer.ops.lower(value, ptr); | ||
| writer.ops.start_write(writer.handle, ptr) | ||
| }; | ||
@@ -434,8 +641,8 @@ rtdebug!("future.write({}, {ptr:?}) = {code:#x}", writer.handle); | ||
| fn start_cancelled(&self, (writer, value): Self::Start) -> Self::Cancel { | ||
| FutureWriteCancel::Cancelled(value, writer) | ||
| fn start_cancelled(&mut self, (writer, value): Self::Start) -> Self::Cancel { | ||
| RawFutureWriteCancel::Cancelled(value, writer) | ||
| } | ||
| fn in_progress_update( | ||
| &self, | ||
| &mut self, | ||
| (mut writer, cleanup): Self::InProgress, | ||
@@ -461,9 +668,4 @@ code: u32, | ||
| // pass here. | ||
| let value = unsafe { (writer.vtable.lift)(ptr) }; | ||
| let value = unsafe { writer.ops.lift(ptr) }; | ||
| let status = if code == super::DROPPED { | ||
| // This writer has been witnessed to be dropped, meaning that | ||
| // `writer` is going to get destroyed soon as this return | ||
| // value propagates up the stack. There's no need to write | ||
| // the default value, so set this to `false`. | ||
| writer.should_write_default_value = false; | ||
| WriteComplete::Dropped(value) | ||
@@ -486,9 +688,6 @@ } else { | ||
| super::COMPLETED => { | ||
| // A value was written, so no need to write the default value. | ||
| writer.should_write_default_value = false; | ||
| // SAFETY: we're the ones managing `ptr` so we know it's safe to | ||
| // pass here. | ||
| unsafe { | ||
| (writer.vtable.dealloc_lists)(ptr); | ||
| writer.ops.dealloc_lists(ptr); | ||
| } | ||
@@ -502,10 +701,10 @@ Ok((WriteComplete::Written, writer)) | ||
| fn in_progress_waitable(&self, (writer, _): &Self::InProgress) -> u32 { | ||
| fn in_progress_waitable(&mut self, (writer, _): &Self::InProgress) -> u32 { | ||
| writer.handle | ||
| } | ||
| fn in_progress_cancel(&self, (writer, _): &Self::InProgress) -> u32 { | ||
| fn in_progress_cancel(&mut self, (writer, _): &mut Self::InProgress) -> u32 { | ||
| // SAFETY: we're managing `writer` and all the various operational bits, | ||
| // so this relies on `WaitableOperation` being safe. | ||
| let code = unsafe { (writer.vtable.cancel_write)(writer.handle) }; | ||
| let code = unsafe { writer.ops.cancel_write(writer.handle) }; | ||
| rtdebug!("future.cancel-write({}) = {code:#x}", writer.handle); | ||
@@ -515,7 +714,7 @@ code | ||
| fn result_into_cancel(&self, (result, writer): Self::Result) -> Self::Cancel { | ||
| fn result_into_cancel(&mut self, (result, writer): Self::Result) -> Self::Cancel { | ||
| match result { | ||
| // The value was actually sent, meaning we can't yield back the | ||
| // future nor the value. | ||
| WriteComplete::Written => FutureWriteCancel::AlreadySent, | ||
| WriteComplete::Written => RawFutureWriteCancel::AlreadySent, | ||
@@ -525,4 +724,4 @@ // The value was not sent because the other end either hung up or we | ||
| // with the writer. | ||
| WriteComplete::Dropped(val) => FutureWriteCancel::Dropped(val), | ||
| WriteComplete::Cancelled(val) => FutureWriteCancel::Cancelled(val, writer), | ||
| WriteComplete::Dropped(val) => RawFutureWriteCancel::Dropped(val), | ||
| WriteComplete::Cancelled(val) => RawFutureWriteCancel::Cancelled(val, writer), | ||
| } | ||
@@ -532,4 +731,4 @@ } | ||
| impl<T: 'static> Future for FutureWrite<T> { | ||
| type Output = Result<(), FutureWriteError<T>>; | ||
| impl<O: FutureOps> Future for RawFutureWrite<O> { | ||
| type Output = Result<(), FutureWriteError<O::Payload>>; | ||
@@ -548,4 +747,4 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| impl<T: 'static> FutureWrite<T> { | ||
| fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureWriteOp<T>>> { | ||
| impl<O: FutureOps> RawFutureWrite<O> { | ||
| fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureWriteOp<O>>> { | ||
| // SAFETY: we've chosen that when `Self` is pinned that it translates to | ||
@@ -556,14 +755,5 @@ // always pinning the inner field, so that's codified here. | ||
| /// Cancel this write if it hasn't already completed. | ||
| /// | ||
| /// This method can be used to cancel a write-in-progress and re-acquire | ||
| /// the writer and the value being sent. Note that the write operation may | ||
| /// succeed racily or the other end may also drop racily, and these | ||
| /// outcomes are reflected in the returned value here. | ||
| /// | ||
| /// # Panics | ||
| /// | ||
| /// Panics if the operation has already been completed via `Future::poll`, | ||
| /// or if this method is called twice. | ||
| pub fn cancel(self: Pin<&mut Self>) -> FutureWriteCancel<T> { | ||
| /// Same as [`FutureWrite::cancel`], but returns a [`RawFutureWriteCancel`] | ||
| /// instead. | ||
| pub fn cancel(self: Pin<&mut Self>) -> RawFutureWriteCancel<O> { | ||
| self.pin_project().cancel() | ||
@@ -596,3 +786,3 @@ } | ||
| #[derive(Debug)] | ||
| pub enum FutureWriteCancel<T: 'static> { | ||
| pub enum RawFutureWriteCancel<O: FutureOps> { | ||
| /// The cancel request raced with the receipt of the sent value, and the | ||
@@ -607,3 +797,3 @@ /// value was actually sent. Neither the value nor the writer are made | ||
| /// writer itself is not longer accessible as it's no longer usable. | ||
| Dropped(T), | ||
| Dropped(O::Payload), | ||
@@ -613,14 +803,17 @@ /// The pending write was successfully cancelled and the value being written | ||
| /// necessary. | ||
| Cancelled(T, FutureWriter<T>), | ||
| Cancelled(O::Payload, RawFutureWriter<O>), | ||
| } | ||
| /// Represents the readable end of a Component Model `future<T>`. | ||
| pub struct FutureReader<T: 'static> { | ||
| pub type FutureReader<T> = RawFutureReader<&'static FutureVtable<T>>; | ||
| /// Represents the readable end of a Component Model `future<T>`. | ||
| pub struct RawFutureReader<O: FutureOps> { | ||
| handle: AtomicU32, | ||
| vtable: &'static FutureVtable<T>, | ||
| ops: O, | ||
| } | ||
| impl<T> fmt::Debug for FutureReader<T> { | ||
| impl<O: FutureOps> fmt::Debug for RawFutureReader<O> { | ||
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| f.debug_struct("FutureReader") | ||
| f.debug_struct("RawFutureReader") | ||
| .field("handle", &self.handle) | ||
@@ -631,8 +824,14 @@ .finish() | ||
| impl<T> FutureReader<T> { | ||
| #[doc(hidden)] | ||
| pub fn new(handle: u32, vtable: &'static FutureVtable<T>) -> Self { | ||
| impl<O: FutureOps> RawFutureReader<O> { | ||
| /// Raw constructor for a future reader. | ||
| /// | ||
| /// Takes ownership of the `handle` provided. | ||
| /// | ||
| /// # Safety | ||
| /// | ||
| /// The `ops` specified must be both valid and well-typed for `handle`. | ||
| pub unsafe fn new(handle: u32, ops: O) -> Self { | ||
| Self { | ||
| handle: AtomicU32::new(handle), | ||
| vtable, | ||
| ops, | ||
| } | ||
@@ -660,5 +859,5 @@ } | ||
| impl<T> IntoFuture for FutureReader<T> { | ||
| type Output = T; | ||
| type IntoFuture = FutureRead<T>; | ||
| impl<O: FutureOps> IntoFuture for RawFutureReader<O> { | ||
| type Output = O::Payload; | ||
| type IntoFuture = RawFutureRead<O>; | ||
@@ -668,3 +867,3 @@ /// Convert this object into a `Future` which will resolve when a value is | ||
| fn into_future(self) -> Self::IntoFuture { | ||
| FutureRead { | ||
| RawFutureRead { | ||
| op: WaitableOperation::new(FutureReadOp(marker::PhantomData), self), | ||
@@ -675,3 +874,3 @@ } | ||
| impl<T> Drop for FutureReader<T> { | ||
| impl<O: FutureOps> Drop for RawFutureReader<O> { | ||
| fn drop(&mut self) { | ||
@@ -683,3 +882,3 @@ let Some(handle) = self.opt_handle() else { | ||
| rtdebug!("future.drop-readable({handle})"); | ||
| (self.vtable.drop_readable)(handle); | ||
| self.ops.drop_readable(handle); | ||
| } | ||
@@ -693,7 +892,13 @@ } | ||
| /// `IntoFuture`. | ||
| pub struct FutureRead<T: 'static> { | ||
| op: WaitableOperation<FutureReadOp<T>>, | ||
| pub type FutureRead<T> = RawFutureRead<&'static FutureVtable<T>>; | ||
| /// Represents a read operation which may be cancelled prior to completion. | ||
| /// | ||
| /// This represents a read operation on a [`FutureReader`] and is created via | ||
| /// `IntoFuture`. | ||
| pub struct RawFutureRead<O: FutureOps> { | ||
| op: WaitableOperation<FutureReadOp<O>>, | ||
| } | ||
| struct FutureReadOp<T>(marker::PhantomData<T>); | ||
| struct FutureReadOp<O>(marker::PhantomData<O>); | ||
@@ -705,17 +910,14 @@ enum ReadComplete<T> { | ||
| unsafe impl<T> WaitableOp for FutureReadOp<T> | ||
| where | ||
| T: 'static, | ||
| { | ||
| type Start = FutureReader<T>; | ||
| type InProgress = (FutureReader<T>, Option<Cleanup>); | ||
| type Result = (ReadComplete<T>, FutureReader<T>); | ||
| type Cancel = Result<T, FutureReader<T>>; | ||
| unsafe impl<O: FutureOps> WaitableOp for FutureReadOp<O> { | ||
| type Start = RawFutureReader<O>; | ||
| type InProgress = (RawFutureReader<O>, Option<Cleanup>); | ||
| type Result = (ReadComplete<O::Payload>, RawFutureReader<O>); | ||
| type Cancel = Result<O::Payload, RawFutureReader<O>>; | ||
| fn start(&self, reader: Self::Start) -> (u32, Self::InProgress) { | ||
| let (ptr, cleanup) = Cleanup::new(reader.vtable.layout); | ||
| fn start(&mut self, mut reader: Self::Start) -> (u32, Self::InProgress) { | ||
| let (ptr, cleanup) = Cleanup::new(reader.ops.elem_layout()); | ||
| // SAFETY: `ptr` is allocated with `vtable.layout` and should be | ||
| // safe to use here. Its lifetime for the async operation is hinged on | ||
| // `WaitableOperation` being safe. | ||
| let code = unsafe { (reader.vtable.start_read)(reader.handle(), ptr) }; | ||
| let code = unsafe { reader.ops.start_read(reader.handle(), ptr) }; | ||
| rtdebug!("future.read({}, {ptr:?}) = {code:#x}", reader.handle()); | ||
@@ -725,3 +927,3 @@ (code, (reader, cleanup)) | ||
| fn start_cancelled(&self, state: Self::Start) -> Self::Cancel { | ||
| fn start_cancelled(&mut self, state: Self::Start) -> Self::Cancel { | ||
| Err(state) | ||
@@ -731,4 +933,4 @@ } | ||
| fn in_progress_update( | ||
| &self, | ||
| (reader, cleanup): Self::InProgress, | ||
| &mut self, | ||
| (mut reader, cleanup): Self::InProgress, | ||
| code: u32, | ||
@@ -755,3 +957,3 @@ ) -> Result<Self::Result, Self::InProgress> { | ||
| // pass here. | ||
| let value = unsafe { (reader.vtable.lift)(ptr) }; | ||
| let value = unsafe { reader.ops.lift(ptr) }; | ||
| Ok((ReadComplete::Value(value), reader)) | ||
@@ -764,10 +966,10 @@ } | ||
| fn in_progress_waitable(&self, (reader, _): &Self::InProgress) -> u32 { | ||
| fn in_progress_waitable(&mut self, (reader, _): &Self::InProgress) -> u32 { | ||
| reader.handle() | ||
| } | ||
| fn in_progress_cancel(&self, (reader, _): &Self::InProgress) -> u32 { | ||
| fn in_progress_cancel(&mut self, (reader, _): &mut Self::InProgress) -> u32 { | ||
| // SAFETY: we're managing `reader` and all the various operational bits, | ||
| // so this relies on `WaitableOperation` being safe. | ||
| let code = unsafe { (reader.vtable.cancel_read)(reader.handle()) }; | ||
| let code = unsafe { reader.ops.cancel_read(reader.handle()) }; | ||
| rtdebug!("future.cancel-read({}) = {code:#x}", reader.handle()); | ||
@@ -777,3 +979,3 @@ code | ||
| fn result_into_cancel(&self, (value, reader): Self::Result) -> Self::Cancel { | ||
| fn result_into_cancel(&mut self, (value, reader): Self::Result) -> Self::Cancel { | ||
| match value { | ||
@@ -790,4 +992,4 @@ // The value was actually read, so thread that through here. | ||
| impl<T: 'static> Future for FutureRead<T> { | ||
| type Output = T; | ||
| impl<O: FutureOps> Future for RawFutureRead<O> { | ||
| type Output = O::Payload; | ||
@@ -807,4 +1009,4 @@ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| impl<T> FutureRead<T> { | ||
| fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureReadOp<T>>> { | ||
| impl<O: FutureOps> RawFutureRead<O> { | ||
| fn pin_project(self: Pin<&mut Self>) -> Pin<&mut WaitableOperation<FutureReadOp<O>>> { | ||
| // SAFETY: we've chosen that when `Self` is pinned that it translates to | ||
@@ -829,5 +1031,5 @@ // always pinning the inner field, so that's codified here. | ||
| /// then calling `poll` again on `self` will panic. | ||
| pub fn cancel(self: Pin<&mut Self>) -> Result<T, FutureReader<T>> { | ||
| pub fn cancel(self: Pin<&mut Self>) -> Result<O::Payload, RawFutureReader<O>> { | ||
| self.pin_project().cancel() | ||
| } | ||
| } |
@@ -246,3 +246,3 @@ //! For a high-level overview of how this module is implemented see the | ||
| fn start(&self, (writer, buf): Self::Start) -> (u32, Self::InProgress) { | ||
| fn start(&mut self, (writer, buf): Self::Start) -> (u32, Self::InProgress) { | ||
| if writer.done { | ||
@@ -263,3 +263,3 @@ return (DROPPED, (writer, buf)); | ||
| fn start_cancelled(&self, (_writer, buf): Self::Start) -> Self::Cancel { | ||
| fn start_cancelled(&mut self, (_writer, buf): Self::Start) -> Self::Cancel { | ||
| (StreamResult::Cancelled, buf) | ||
@@ -269,3 +269,3 @@ } | ||
| fn in_progress_update( | ||
| &self, | ||
| &mut self, | ||
| (writer, mut buf): Self::InProgress, | ||
@@ -291,7 +291,7 @@ code: u32, | ||
| fn in_progress_waitable(&self, (writer, _): &Self::InProgress) -> u32 { | ||
| fn in_progress_waitable(&mut self, (writer, _): &Self::InProgress) -> u32 { | ||
| writer.handle | ||
| } | ||
| fn in_progress_cancel(&self, (writer, _): &Self::InProgress) -> u32 { | ||
| fn in_progress_cancel(&mut self, (writer, _): &mut Self::InProgress) -> u32 { | ||
| // SAFETY: we're managing `writer` and all the various operational bits, | ||
@@ -304,3 +304,3 @@ // so this relies on `WaitableOperation` being safe. | ||
| fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel { | ||
| fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel { | ||
| result | ||
@@ -468,3 +468,3 @@ } | ||
| fn start(&self, (reader, mut buf): Self::Start) -> (u32, Self::InProgress) { | ||
| fn start(&mut self, (reader, mut buf): Self::Start) -> (u32, Self::InProgress) { | ||
| if reader.done { | ||
@@ -502,3 +502,3 @@ return (DROPPED, (reader, buf, None)); | ||
| fn start_cancelled(&self, (_, buf): Self::Start) -> Self::Cancel { | ||
| fn start_cancelled(&mut self, (_, buf): Self::Start) -> Self::Cancel { | ||
| (StreamResult::Cancelled, buf) | ||
@@ -508,3 +508,3 @@ } | ||
| fn in_progress_update( | ||
| &self, | ||
| &mut self, | ||
| (reader, mut buf, cleanup): Self::InProgress, | ||
@@ -566,7 +566,7 @@ code: u32, | ||
| fn in_progress_waitable(&self, (reader, ..): &Self::InProgress) -> u32 { | ||
| fn in_progress_waitable(&mut self, (reader, ..): &Self::InProgress) -> u32 { | ||
| reader.handle() | ||
| } | ||
| fn in_progress_cancel(&self, (reader, ..): &Self::InProgress) -> u32 { | ||
| fn in_progress_cancel(&mut self, (reader, ..): &mut Self::InProgress) -> u32 { | ||
| // SAFETY: we're managing `reader` and all the various operational bits, | ||
@@ -579,3 +579,3 @@ // so this relies on `WaitableOperation` being safe. | ||
| fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel { | ||
| fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel { | ||
| result | ||
@@ -582,0 +582,0 @@ } |
@@ -45,10 +45,10 @@ //! Bindings used to manage subtasks, or invocations of imported functions. | ||
| /// parameters coming first. | ||
| fn abi_layout(&self) -> Layout; | ||
| fn abi_layout(&mut self) -> Layout; | ||
| /// The offset, in bytes, from the start of `ABI_LAYOUT` to where the | ||
| /// results will be stored. | ||
| fn results_offset(&self) -> usize; | ||
| fn results_offset(&mut self) -> usize; | ||
| /// The raw function import using `[async-lower]` and the canonical ABI. | ||
| unsafe fn call_import(&self, params: Self::ParamsLower, results: *mut u8) -> u32; | ||
| unsafe fn call_import(&mut self, params: Self::ParamsLower, results: *mut u8) -> u32; | ||
@@ -64,18 +64,18 @@ /// Bindings-generated version of lowering `params`. | ||
| /// ABI). | ||
| unsafe fn params_lower(&self, params: Self::Params, dst: *mut u8) -> Self::ParamsLower; | ||
| unsafe fn params_lower(&mut self, params: Self::Params, dst: *mut u8) -> Self::ParamsLower; | ||
| /// Bindings-generated version of deallocating any lists stored within | ||
| /// `lower`. | ||
| unsafe fn params_dealloc_lists(&self, lower: Self::ParamsLower); | ||
| unsafe fn params_dealloc_lists(&mut self, lower: Self::ParamsLower); | ||
| /// Bindings-generated version of deallocating not only owned lists within | ||
| /// `lower` but also deallocating any owned resources. | ||
| unsafe fn params_dealloc_lists_and_own(&self, lower: Self::ParamsLower); | ||
| unsafe fn params_dealloc_lists_and_own(&mut self, lower: Self::ParamsLower); | ||
| /// Bindings-generated version of lifting the results stored at `src`. | ||
| unsafe fn results_lift(&self, src: *mut u8) -> Self::Results; | ||
| unsafe fn results_lift(&mut self, src: *mut u8) -> Self::Results; | ||
| /// Helper function to actually perform this asynchronous call with | ||
| /// `params`. | ||
| fn call(&self, params: Self::Params) -> impl Future<Output = Self::Results> | ||
| fn call(&mut self, params: Self::Params) -> impl Future<Output = Self::Results> | ||
| where | ||
@@ -98,3 +98,3 @@ Self: Sized, | ||
| struct SubtaskOps<'a, T>(&'a T); | ||
| struct SubtaskOps<'a, T>(&'a mut T); | ||
@@ -111,3 +111,3 @@ struct Start<T: Subtask> { | ||
| fn start(&self, state: Self::Start) -> (u32, Self::InProgress) { | ||
| fn start(&mut self, state: Self::Start) -> (u32, Self::InProgress) { | ||
| unsafe { | ||
@@ -135,3 +135,3 @@ let (ptr_params, cleanup) = Cleanup::new(self.0.abi_layout()); | ||
| fn start_cancelled(&self, _state: Self::Start) -> Self::Cancel { | ||
| fn start_cancelled(&mut self, _state: Self::Start) -> Self::Cancel { | ||
| Err(()) | ||
@@ -141,3 +141,3 @@ } | ||
| fn in_progress_update( | ||
| &self, | ||
| &mut self, | ||
| mut state: Self::InProgress, | ||
@@ -173,3 +173,4 @@ code: u32, | ||
| // itself. | ||
| unsafe { Ok(Ok(self.0.results_lift(state.ptr_results(self.0)))) } | ||
| let ptr = state.ptr_results(self.0); | ||
| unsafe { Ok(Ok(self.0.results_lift(ptr))) } | ||
| } | ||
@@ -219,3 +220,3 @@ | ||
| fn in_progress_waitable(&self, state: &Self::InProgress) -> u32 { | ||
| fn in_progress_waitable(&mut self, state: &Self::InProgress) -> u32 { | ||
| // This shouldn't get called in the one case this isn't present: when | ||
@@ -227,7 +228,7 @@ // `STATUS_RETURNED` is returned and no waitable is created. That's the | ||
| fn in_progress_cancel(&self, state: &Self::InProgress) -> u32 { | ||
| fn in_progress_cancel(&mut self, state: &mut Self::InProgress) -> u32 { | ||
| unsafe { cancel(self.in_progress_waitable(state)) } | ||
| } | ||
| fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel { | ||
| fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel { | ||
| result | ||
@@ -259,3 +260,3 @@ } | ||
| impl<T: Subtask> InProgress<T> { | ||
| fn flag_started(&mut self, op: &T) { | ||
| fn flag_started(&mut self, op: &mut T) { | ||
| assert!(!self.started); | ||
@@ -272,3 +273,3 @@ self.started = true; | ||
| fn ptr_results(&self, op: &T) -> *mut u8 { | ||
| fn ptr_results(&mut self, op: &mut T) -> *mut u8 { | ||
| // SAFETY: the `T` trait has unsafely promised us that the offset is | ||
@@ -275,0 +276,0 @@ // in-bounds of the allocation layout. |
@@ -87,3 +87,3 @@ //! Generic support for "any waitable" and performing asynchronous operations on | ||
| /// along with the `InProgress` state. | ||
| fn start(&self, state: Self::Start) -> (u32, Self::InProgress); | ||
| fn start(&mut self, state: Self::Start) -> (u32, Self::InProgress); | ||
@@ -99,3 +99,3 @@ /// Optionally complete the async operation. | ||
| fn in_progress_update( | ||
| &self, | ||
| &mut self, | ||
| state: Self::InProgress, | ||
@@ -107,7 +107,7 @@ code: u32, | ||
| /// operation is cancelled before it's started. | ||
| fn start_cancelled(&self, state: Self::Start) -> Self::Cancel; | ||
| fn start_cancelled(&mut self, state: Self::Start) -> Self::Cancel; | ||
| /// Acquires the component-model `waitable` index that the `InProgress` | ||
| /// state is waiting on. | ||
| fn in_progress_waitable(&self, state: &Self::InProgress) -> u32; | ||
| fn in_progress_waitable(&mut self, state: &Self::InProgress) -> u32; | ||
@@ -123,3 +123,3 @@ /// Initiates a request for cancellation of this operation. Returns the | ||
| /// component model ABI, for example. | ||
| fn in_progress_cancel(&self, state: &Self::InProgress) -> u32; | ||
| fn in_progress_cancel(&mut self, state: &mut Self::InProgress) -> u32; | ||
@@ -129,3 +129,3 @@ /// Converts a "completion result" into a "cancel result". This is necessary | ||
| /// first acquired and then transitioned to a cancel request. | ||
| fn result_into_cancel(&self, result: Self::Result) -> Self::Cancel; | ||
| fn result_into_cancel(&mut self, result: Self::Result) -> Self::Cancel; | ||
| } | ||
@@ -159,3 +159,3 @@ | ||
| ) -> ( | ||
| &S, | ||
| &mut S, | ||
| &mut WaitableOperationState<S>, | ||
@@ -172,3 +172,3 @@ Pin<&mut CompletionStatus>, | ||
| ( | ||
| &me.op, | ||
| &mut me.op, | ||
| &mut me.state, | ||
@@ -451,2 +451,7 @@ Pin::new_unchecked(&mut me.completion_status), | ||
| } | ||
| /// Returns whether or not this operation has completed. | ||
| pub fn is_done(&self) -> bool { | ||
| matches!(self.state, WaitableOperationState::Done) | ||
| } | ||
| } | ||
@@ -464,13 +469,11 @@ | ||
| fn drop(&mut self) { | ||
| // SAFETY: we're in the destructor here so the value `self` is about | ||
| // to go away and we can guarantee we're not moving out of it. | ||
| let mut pin = unsafe { Pin::new_unchecked(self) }; | ||
| let (_, state, _) = pin.as_mut().pin_project(); | ||
| // If this operation has already completed then skip cancellation, | ||
| // otherwise it's our job to cancel anything in-flight. | ||
| if let WaitableOperationState::Done = state { | ||
| if self.is_done() { | ||
| return; | ||
| } | ||
| // SAFETY: we're in the destructor here so the value `self` is about | ||
| // to go away and we can guarantee we're not moving out of it. | ||
| let pin = unsafe { Pin::new_unchecked(self) }; | ||
| pin.cancel(); | ||
@@ -477,0 +480,0 @@ } |
@@ -5,7 +5,7 @@ // This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh | ||
| extern void *cabi_realloc_wit_bindgen_0_47_0(void *ptr, size_t old_size, size_t align, size_t new_size); | ||
| extern void *cabi_realloc_wit_bindgen_0_48_0(void *ptr, size_t old_size, size_t align, size_t new_size); | ||
| __attribute__((__weak__, __export_name__("cabi_realloc"))) | ||
| void *cabi_realloc(void *ptr, size_t old_size, size_t align, size_t new_size) { | ||
| return cabi_realloc_wit_bindgen_0_47_0(ptr, old_size, align, new_size); | ||
| return cabi_realloc_wit_bindgen_0_48_0(ptr, old_size, align, new_size); | ||
| } |
| // This file is generated by ./ci/rebuild-libwit-bindgen-cabi.sh | ||
| #[unsafe(no_mangle)] | ||
| pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_47_0( | ||
| pub unsafe extern "C" fn cabi_realloc_wit_bindgen_0_48_0( | ||
| old_ptr: *mut u8, | ||
@@ -6,0 +6,0 @@ old_len: usize, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet