shared_memory_server/
lib.rs

1#![allow(clippy::missing_safety_doc)]
2
3use self::channel::ShmemChannel;
4use eyre::{eyre, Context};
5use serde::{Deserialize, Serialize};
6pub use shared_memory_extended::{Shmem, ShmemConf};
7use std::marker::PhantomData;
8use std::time::Duration;
9
10mod channel;
11
12pub struct ShmemServer<T, U> {
13    channel: ShmemChannel,
14    reply_expected: bool,
15    phantom: PhantomData<(T, U)>,
16}
17
18impl<T, U> ShmemServer<T, U> {
19    pub unsafe fn new(memory: Shmem) -> eyre::Result<Self> {
20        Ok(Self {
21            channel: ShmemChannel::new_server(memory)?,
22            reply_expected: false,
23            phantom: PhantomData,
24        })
25    }
26
27    pub fn listen(&mut self) -> eyre::Result<Option<T>>
28    where
29        T: for<'a> Deserialize<'a> + std::fmt::Debug,
30    {
31        assert!(!self.reply_expected);
32        let result = self.channel.receive(None);
33        if matches!(result, Ok(Some(_))) {
34            self.reply_expected = true;
35        }
36
37        result
38    }
39
40    pub fn send_reply(&mut self, value: &U) -> eyre::Result<()>
41    where
42        U: Serialize + std::fmt::Debug,
43    {
44        assert!(self.reply_expected);
45        self.channel.send(value)?;
46        self.reply_expected = false;
47        Ok(())
48    }
49}
50
51pub struct ShmemClient<T, U> {
52    channel: ShmemChannel,
53    timeout: Option<Duration>,
54    phantom: PhantomData<(T, U)>,
55}
56
57impl<T, U> ShmemClient<T, U> {
58    pub unsafe fn new(memory: Shmem, timeout: Option<Duration>) -> eyre::Result<Self> {
59        Ok(Self {
60            channel: ShmemChannel::new_client(memory)?,
61            timeout,
62            phantom: PhantomData,
63        })
64    }
65
66    pub fn request(&mut self, value: &T) -> eyre::Result<U>
67    where
68        T: Serialize + std::fmt::Debug,
69        U: for<'a> Deserialize<'a> + std::fmt::Debug,
70    {
71        self.channel
72            .send(value)
73            .wrap_err("failed to send request")?;
74        self.channel
75            .receive(self.timeout)
76            .wrap_err("failed to receive reply")?
77            .ok_or_else(|| eyre!("server disconnected unexpectedly"))
78    }
79}