server/deferred/
lend_mut.rs

1// SPDX-FileCopyrightText: 2023 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use xous::MessageSender;
5
6use crate::{LendMut, LendMutResponse, Server, ServerContext, SimpleMemoryMessage};
7/// An [`DeferredLendMut`] message handler that can defer the response
8pub trait DeferredLendMutHandler<M>
9where
10    M: LendMut,
11    Self: Server,
12{
13    fn handle(&mut self, msg: DeferredLendMut<M>, context: &mut ServerContext<Self>);
14    fn default_response() -> M::Response;
15}
16
17/// An encapsulated blocking [`LendMut`] message, which can be responded to
18/// later during execution. It can be stored, and will return the message when
19/// dropped, or the [`DeferredLendMut::set_response`] function is called.
20#[derive(Debug)]
21pub struct DeferredLendMut<M: LendMut> {
22    sender: MessageSender,
23    body: Option<M>,
24    response: Option<M::Response>,
25}
26
27impl<M: LendMut> DeferredLendMut<M> {
28    pub(crate) fn new(mut envelope: xous::MessageEnvelope, response: M::Response) -> Option<Self> {
29        let sender = envelope.sender;
30        let body = if let xous::Message::MutableBorrow(mem) = &mut envelope.body {
31            M::from(SimpleMemoryMessage::from(&*mem))
32        } else {
33            log::warn!("invalid message: {envelope:?}");
34            return None;
35        };
36        // In some feature combinations envelope does not do anything when dropped.
37        #[allow(clippy::forget_non_drop)]
38        core::mem::forget(envelope);
39        Some(Self { sender, body: Some(body), response: Some(response) })
40    }
41
42    /// Returns the PID of the sender
43    pub fn pid(&self) -> xous::PID { self.sender.pid().unwrap() }
44
45    /// Get a reference to the parsed message body.
46    pub fn body(&self) -> &M { self.body.as_ref().unwrap() }
47
48    /// Get a mutable reference to the parsed message body.
49    pub fn body_mut(&mut self) -> &mut M { self.body.as_mut().unwrap() }
50
51    /// Get a mutable reference to the parsed message body.
52    pub fn set_response(&mut self, response: M::Response) { self.response = Some(response) }
53}
54
55impl<M: LendMut> Drop for DeferredLendMut<M> {
56    fn drop(&mut self) {
57        let simple: SimpleMemoryMessage = self.body.take().unwrap().into();
58        let (arg1, arg2) = self.response.take().unwrap().to_usize_pair();
59        xous::syscall::return_memory_offset_valid(
60            self.sender,
61            simple.buf,
62            xous::MemoryAddress::new(arg1),
63            xous::MemoryAddress::new(arg2),
64        )
65        .expect("couldn't return memory")
66    }
67}
68
69/// Message handler, used by ServerMessages::messages()
70pub fn handle_deferred_lend_mut<M, S>(
71    handler: &mut S,
72    raw: xous::MessageEnvelope,
73    context: &mut ServerContext<S>,
74) where
75    M: LendMut + 'static,
76    S: Server + DeferredLendMutHandler<M>,
77{
78    let Some(deferred) = DeferredLendMut::new(raw, S::default_response()) else { return };
79    handler.handle(deferred, context);
80}