Skip to main content

kernel_api/sync/
send_wrapper.rs

1use core::mem::{ManuallyDrop, MaybeUninit};
2use core::ptr::addr_of_mut;
3use crate::address_space::WeakAddressSpace;
4
5#[derive(Debug)]
6pub struct SendWrapper<T> {
7	inner: ManuallyDrop<T>,
8	address_space: ManuallyDrop<WeakAddressSpace>,
9}
10
11unsafe impl<T> Send for SendWrapper<T> {}
12
13impl<T> SendWrapper<T> {
14	pub fn new(inner: T) -> Self {
15		let mut address_space = MaybeUninit::<WeakAddressSpace>::uninit();
16		crate::bridge::threading::with_current_thread(address_space.as_mut_ptr().cast(), |meta, out| {
17			unsafe { core::ptr::write(out.cast::<WeakAddressSpace>(), meta.address_space.downgrade()) };
18		});
19		Self {
20			inner: ManuallyDrop::new(inner),
21			address_space: ManuallyDrop::new(unsafe { address_space.assume_init() }),
22		}
23	}
24
25	pub fn into_inner(self) -> T {
26		let mut this = ManuallyDrop::new(self);
27		this.into_inner_helper()
28	}
29
30	fn into_inner_helper(&mut self) -> T {
31		let weak = unsafe { ManuallyDrop::take(&mut self.address_space) };
32		let is_current = MaybeUninit::<bool>::uninit();
33		let mut payload = (weak, is_current);
34		crate::bridge::threading::with_current_thread(addr_of_mut!(payload).cast(), |meta, payload| {
35			let payload = unsafe { &mut *payload.cast::<(WeakAddressSpace, MaybeUninit<bool>)>() };
36			let is_current = WeakAddressSpace::ptr_eq(&payload.0, &meta.address_space);
37			payload.1.write(is_current);
38		});
39
40		if unsafe { payload.1.assume_init() } {
41			unsafe { ManuallyDrop::take(&mut self.inner) }
42		} else {
43			panic!("attempted to drop or unwrap `SendWrapper` in wrong address space")
44		}
45	}
46}
47
48impl<T> Drop for SendWrapper<T> {
49	fn drop(&mut self) {
50		self.into_inner_helper();
51	}
52}