servo_base/generic_channel/
oneshot.rs1use std::fmt;
6use std::marker::PhantomData;
7use std::panic::Location;
8
9use serde::{Deserialize, Deserializer, Serialize, Serializer};
10
11use crate::generic_channel::{
12 GenericReceiverVariants, GenericSenderVariants, GenericSenderVisitor, ReceiveResult, SendError,
13 SendResult, serialize_generic_sender_variants, use_ipc,
14};
15
16pub struct GenericOneshotSender<T: Serialize>(GenericSenderVariants<T>);
18
19impl<T: Serialize> GenericOneshotSender<T> {
20 #[inline]
21 pub fn send(self, msg: T) -> SendResult {
23 match self.0 {
24 GenericSenderVariants::Ipc(ref sender) => sender
25 .send(msg)
26 .map_err(|e| SendError::SerializationError(format!("{e}"))),
27 GenericSenderVariants::Crossbeam(ref sender) => {
28 sender.send(Ok(msg)).map_err(|_| SendError::Disconnected)
29 },
30 }
31 }
32
33 #[inline]
34 #[track_caller]
35 pub fn send_or_warn(self, msg: T) {
37 if let Err(error) = self.send(msg) {
38 let location = Location::caller();
39 log::warn!("Failed to send msg due to `{error}` at {location:?}");
40 }
41 }
42
43 #[inline]
44 pub fn send_or_ignore(self, msg: T) {
46 let _ = self.send(msg);
47 }
48}
49
50impl<T> GenericOneshotReceiver<T>
51where
52 T: for<'de> Deserialize<'de> + Serialize,
53{
54 #[inline]
55 pub fn recv(self) -> ReceiveResult<T> {
57 match self.0 {
58 GenericReceiverVariants::Ipc(ref receiver) => Ok(receiver.recv()?),
59 GenericReceiverVariants::Crossbeam(ref receiver) => {
60 let msg = receiver.recv()?;
62 Ok(msg.expect("Infallible"))
65 },
66 }
67 }
68}
69
70pub struct GenericOneshotReceiver<T: Serialize + for<'de> Deserialize<'de>>(
72 GenericReceiverVariants<T>,
73);
74
75pub fn oneshot<T>() -> Option<(GenericOneshotSender<T>, GenericOneshotReceiver<T>)>
79where
80 T: for<'de> Deserialize<'de> + Serialize,
81{
82 if use_ipc() {
83 ipc_channel::ipc::channel()
84 .map(|(tx, rx)| {
85 (
86 GenericOneshotSender(GenericSenderVariants::Ipc(tx)),
87 GenericOneshotReceiver(GenericReceiverVariants::Ipc(rx)),
88 )
89 })
90 .ok()
91 } else {
92 let (rx, tx) = crossbeam_channel::bounded(1);
93 Some((
94 GenericOneshotSender(GenericSenderVariants::Crossbeam(rx)),
95 GenericOneshotReceiver(GenericReceiverVariants::Crossbeam(tx)),
96 ))
97 }
98}
99
100impl<T: Serialize> Serialize for GenericOneshotSender<T> {
101 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
102 serialize_generic_sender_variants(&self.0, s)
103 }
104}
105
106impl<'a, T: Serialize + Deserialize<'a>> Deserialize<'a> for GenericOneshotSender<T> {
107 fn deserialize<D>(d: D) -> Result<GenericOneshotSender<T>, D::Error>
108 where
109 D: Deserializer<'a>,
110 {
111 d.deserialize_enum(
112 "GenericSender",
113 &["Ipc", "Crossbeam"],
114 GenericSenderVisitor {
115 marker: PhantomData,
116 },
117 )
118 .map(|variant| GenericOneshotSender(variant))
119 }
120}
121
122impl<T: Serialize> fmt::Debug for GenericOneshotSender<T> {
123 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124 write!(f, "Sender(..)")
125 }
126}