kernel_api/sync/
send_wrapper.rs1use 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}