shared_memory_server/
lib.rs1#![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}