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>)>
80where
81 T: for<'de> Deserialize<'de> + Serialize,
82{
83 if use_ipc() {
84 ipc_channel::ipc::channel()
85 .map(|(tx, rx)| {
86 (
87 GenericOneshotSender(GenericSenderVariants::Ipc(tx)),
88 GenericOneshotReceiver(GenericReceiverVariants::Ipc(rx)),
89 )
90 })
91 .ok()
92 } else {
93 let (rx, tx) = crossbeam_channel::bounded(1);
94 Some((
95 GenericOneshotSender(GenericSenderVariants::Crossbeam(rx)),
96 GenericOneshotReceiver(GenericReceiverVariants::Crossbeam(tx)),
97 ))
98 }
99}
100
101impl<T: Serialize> Serialize for GenericOneshotSender<T> {
102 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
103 serialize_generic_sender_variants(&self.0, s)
104 }
105}
106
107impl<'a, T: Serialize + Deserialize<'a>> Deserialize<'a> for GenericOneshotSender<T> {
108 fn deserialize<D>(d: D) -> Result<GenericOneshotSender<T>, D::Error>
109 where
110 D: Deserializer<'a>,
111 {
112 d.deserialize_enum(
113 "GenericSender",
114 &["Ipc", "Crossbeam"],
115 GenericSenderVisitor {
116 marker: PhantomData,
117 },
118 )
119 .map(|variant| GenericOneshotSender(variant))
120 }
121}
122
123impl<T: Serialize> fmt::Debug for GenericOneshotSender<T> {
124 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
125 write!(f, "Sender(..)")
126 }
127}