1use std::fmt::Display;
8use std::marker::PhantomData;
9use std::panic::Location;
10use std::sync::OnceLock;
11use std::time::Duration;
12use std::{fmt, io};
13
14use crossbeam_channel::RecvTimeoutError;
15use ipc_channel::router::ROUTER;
16use ipc_channel::{IpcError, SerDeError};
17use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
18use malloc_size_of_derive::MallocSizeOf;
19use serde::de::VariantAccess;
20use serde::{Deserialize, Deserializer, Serialize, Serializer};
21use servo_config::opts;
22
23mod callback;
24pub use callback::GenericCallback;
25mod lazy_callback;
26pub use lazy_callback::{CallbackSetter, LazyCallback, lazy_callback};
27mod oneshot;
28mod shared_memory;
29pub use oneshot::{GenericOneshotReceiver, GenericOneshotSender, oneshot};
30pub use shared_memory::GenericSharedMemory;
31mod generic_channelset;
32pub use generic_channelset::{GenericReceiverSet, GenericSelectionResult};
33mod buffered;
34pub use buffered::GenericBufferedSender;
35
36static USE_IPC: OnceLock<bool> = OnceLock::new();
38
39fn use_ipc() -> bool {
41 *USE_IPC.get_or_init(|| {
42 servo_config::opts::get().multiprocess || servo_config::opts::get().force_ipc
43 })
44}
45
46pub trait GenericSend<T>
49where
50 T: serde::Serialize + for<'de> serde::Deserialize<'de>,
51{
52 fn send(&self, _: T) -> SendResult;
54
55 #[track_caller]
60 fn send_or_warn(&self, message: T) {
61 if let Err(error) = self.send(message) {
62 let location = Location::caller();
63 log::warn!("Failed to send msg due to `{error}` at {location:?}");
64 }
65 }
66
67 fn send_or_ignore(&self, message: T) {
73 let _ = self.send(message);
74 }
75
76 fn sender(&self) -> GenericSender<T>;
78}
79
80pub struct GenericSender<T: Serialize>(GenericSenderVariants<T>);
84
85enum GenericSenderVariants<T: Serialize> {
90 Ipc(ipc_channel::ipc::IpcSender<T>),
91 Crossbeam(crossbeam_channel::Sender<Result<T, SendError>>),
99}
100
101fn serialize_generic_sender_variants<T: Serialize, S: Serializer>(
102 value: &GenericSenderVariants<T>,
103 s: S,
104) -> Result<S::Ok, S::Error> {
105 match value {
106 GenericSenderVariants::Ipc(sender) => {
107 s.serialize_newtype_variant("GenericSender", 0, "Ipc", sender)
108 },
109 GenericSenderVariants::Crossbeam(sender) => {
120 if opts::get().multiprocess {
121 return Err(serde::ser::Error::custom(
122 "Crossbeam channel found in multiprocess mode!",
123 ));
124 } let sender_clone_addr = Box::leak(Box::new(sender.clone())) as *mut _ as usize;
127 s.serialize_newtype_variant("GenericSender", 1, "Crossbeam", &sender_clone_addr)
128 },
129 }
130}
131
132impl<T: Serialize> Serialize for GenericSender<T> {
133 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
134 serialize_generic_sender_variants(&self.0, s)
135 }
136}
137
138struct GenericSenderVisitor<T> {
139 marker: PhantomData<T>,
140}
141
142impl<'de, T: Serialize + Deserialize<'de>> serde::de::Visitor<'de> for GenericSenderVisitor<T> {
143 type Value = GenericSenderVariants<T>;
144
145 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
146 formatter.write_str("a GenericSender variant")
147 }
148
149 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
150 where
151 A: serde::de::EnumAccess<'de>,
152 {
153 #[derive(Deserialize)]
154 enum GenericSenderVariantNames {
155 Ipc,
156 Crossbeam,
157 }
158
159 let (variant_name, variant_data): (GenericSenderVariantNames, _) = data.variant()?;
160
161 match variant_name {
162 GenericSenderVariantNames::Ipc => variant_data
163 .newtype_variant::<ipc_channel::ipc::IpcSender<T>>()
164 .map(|sender| GenericSenderVariants::Ipc(sender)),
165 GenericSenderVariantNames::Crossbeam => {
166 if opts::get().multiprocess {
167 return Err(serde::de::Error::custom(
168 "Crossbeam channel found in multiprocess mode!",
169 ));
170 }
171 let addr = variant_data.newtype_variant::<usize>()?;
172 let ptr = addr as *mut crossbeam_channel::Sender<Result<T, SendError>>;
173 #[expect(unsafe_code)]
176 let sender = unsafe { Box::from_raw(ptr) };
177 Ok(GenericSenderVariants::Crossbeam(*sender))
178 },
179 }
180 }
181}
182
183impl<'a, T: Serialize + Deserialize<'a>> Deserialize<'a> for GenericSender<T> {
184 fn deserialize<D>(d: D) -> Result<GenericSender<T>, D::Error>
185 where
186 D: Deserializer<'a>,
187 {
188 d.deserialize_enum(
189 "GenericSender",
190 &["Ipc", "Crossbeam"],
191 GenericSenderVisitor {
192 marker: PhantomData,
193 },
194 )
195 .map(|variant| GenericSender(variant))
196 }
197}
198
199impl<T> Clone for GenericSender<T>
200where
201 T: Serialize,
202{
203 fn clone(&self) -> Self {
204 match &self.0 {
205 GenericSenderVariants::Ipc(chan) => {
206 GenericSender(GenericSenderVariants::Ipc(chan.clone()))
207 },
208 GenericSenderVariants::Crossbeam(chan) => {
209 GenericSender(GenericSenderVariants::Crossbeam(chan.clone()))
210 },
211 }
212 }
213}
214
215impl<T: Serialize> fmt::Debug for GenericSender<T> {
216 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
217 write!(f, "Sender(..)")
218 }
219}
220
221impl<T: Serialize> GenericSender<T> {
222 #[inline]
223 pub fn send(&self, msg: T) -> SendResult {
224 match &self.0 {
225 GenericSenderVariants::Ipc(sender) => sender
226 .send(msg)
227 .map_err(|e| SendError::SerializationError(e.to_string())),
228 GenericSenderVariants::Crossbeam(sender) => {
229 sender.send(Ok(msg)).map_err(|_| SendError::Disconnected)
230 },
231 }
232 }
233
234 #[inline]
239 pub fn send_or_warn(&self, msg: T) {
240 if let Err(error) = self.send(msg) {
241 let location = Location::caller();
242 log::warn!("Failed to send msg due to `{error}` at {location:?}");
243 }
244 }
245
246 #[inline]
252 pub fn send_or_ignore(&self, msg: T) {
253 let _ = self.send(msg);
254 }
255}
256
257impl<T: Serialize> MallocSizeOf for GenericSender<T> {
258 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
259 match &self.0 {
260 GenericSenderVariants::Ipc(ipc_sender) => ipc_sender.size_of(ops),
261 GenericSenderVariants::Crossbeam(sender) => sender.size_of(ops),
262 }
263 }
264}
265
266#[derive(Debug)]
267pub enum SendError {
268 Disconnected,
269 SerializationError(String),
270}
271
272impl From<IpcError> for SendError {
273 fn from(value: IpcError) -> Self {
274 match value {
275 IpcError::SerializationError(ser_de_error) => {
276 SendError::SerializationError(ser_de_error.to_string())
277 },
278 IpcError::Io(error) => {
279 log::error!("IO Error in ipc {:?}", error);
280 SendError::Disconnected
281 },
282 IpcError::Disconnected => SendError::Disconnected,
283 }
284 }
285}
286
287impl From<SerDeError> for SendError {
288 fn from(value: SerDeError) -> Self {
289 SendError::SerializationError(value.to_string())
290 }
291}
292
293impl From<io::Error> for SendError {
294 fn from(value: io::Error) -> Self {
295 log::error!("IO Error in IPC {:?}", value);
296 SendError::Disconnected
297 }
298}
299
300impl Display for SendError {
301 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
302 write!(f, "{self:?}")
303 }
304}
305
306pub type SendResult = Result<(), SendError>;
307
308#[derive(Debug)]
309pub enum ReceiveError {
310 DeserializationFailed(String),
311 Io(std::io::Error),
313 Disconnected,
315}
316
317impl From<IpcError> for ReceiveError {
318 fn from(e: IpcError) -> Self {
319 match e {
320 IpcError::Disconnected => ReceiveError::Disconnected,
321 IpcError::Io(reason) => ReceiveError::Io(reason),
322 IpcError::SerializationError(ser_de_error) => {
323 ReceiveError::DeserializationFailed(ser_de_error.to_string())
324 },
325 }
326 }
327}
328
329impl From<crossbeam_channel::RecvError> for ReceiveError {
330 fn from(_: crossbeam_channel::RecvError) -> Self {
331 ReceiveError::Disconnected
332 }
333}
334
335impl fmt::Display for ReceiveError {
336 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
337 match *self {
338 ReceiveError::DeserializationFailed(ref error) => {
339 write!(fmt, "deserialization error: {error}")
340 },
341 ReceiveError::Io(ref error) => write!(fmt, "io error: {error}"),
342 ReceiveError::Disconnected => write!(fmt, "disconnected"),
343 }
344 }
345}
346impl From<std::io::Error> for ReceiveError {
347 fn from(value: std::io::Error) -> Self {
348 ReceiveError::Io(value)
349 }
350}
351
352pub enum TryReceiveError {
353 Empty,
354 ReceiveError(ReceiveError),
355}
356
357impl From<crossbeam_channel::RecvTimeoutError> for TryReceiveError {
358 fn from(value: crossbeam_channel::RecvTimeoutError) -> Self {
359 match value {
360 RecvTimeoutError::Timeout => TryReceiveError::Empty,
361 RecvTimeoutError::Disconnected => {
362 TryReceiveError::ReceiveError(ReceiveError::Disconnected)
363 },
364 }
365 }
366}
367
368impl From<ipc_channel::TryRecvError> for TryReceiveError {
369 fn from(e: ipc_channel::TryRecvError) -> Self {
370 match e {
371 ipc_channel::TryRecvError::Empty => TryReceiveError::Empty,
372 ipc_channel::TryRecvError::IpcError(inner) => {
373 TryReceiveError::ReceiveError(inner.into())
374 },
375 }
376 }
377}
378
379impl From<crossbeam_channel::TryRecvError> for TryReceiveError {
380 fn from(e: crossbeam_channel::TryRecvError) -> Self {
381 match e {
382 crossbeam_channel::TryRecvError::Empty => TryReceiveError::Empty,
383 crossbeam_channel::TryRecvError::Disconnected => {
384 TryReceiveError::ReceiveError(ReceiveError::Disconnected)
385 },
386 }
387 }
388}
389
390pub type RoutedReceiver<T> = crossbeam_channel::Receiver<Result<T, SendError>>;
391pub type ReceiveResult<T> = Result<T, ReceiveError>;
392pub type TryReceiveResult<T> = Result<T, TryReceiveError>;
393pub type RoutedReceiverReceiveResult<T> =
394 Result<Result<T, SendError>, crossbeam_channel::RecvError>;
395
396pub fn to_receive_result<T>(receive_result: RoutedReceiverReceiveResult<T>) -> ReceiveResult<T> {
397 match receive_result {
398 Ok(Ok(msg)) => Ok(msg),
399 Err(_crossbeam_recv_err) => Err(ReceiveError::Disconnected),
400 Ok(Err(ipc_err)) => Err(ReceiveError::DeserializationFailed(ipc_err.to_string())),
401 }
402}
403
404#[derive(MallocSizeOf)]
405pub struct GenericReceiver<T>(GenericReceiverVariants<T>)
406where
407 T: for<'de> Deserialize<'de> + Serialize;
408
409impl<T> std::fmt::Debug for GenericReceiver<T>
410where
411 T: for<'de> Deserialize<'de> + Serialize,
412{
413 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414 f.debug_tuple("GenericReceiver").finish()
415 }
416}
417
418#[derive(MallocSizeOf)]
419enum GenericReceiverVariants<T>
420where
421 T: for<'de> Deserialize<'de> + Serialize,
422{
423 Ipc(ipc_channel::ipc::IpcReceiver<T>),
424 Crossbeam(RoutedReceiver<T>),
425}
426
427impl<T> GenericReceiver<T>
428where
429 T: for<'de> Deserialize<'de> + Serialize,
430{
431 #[inline]
432 pub fn recv(&self) -> ReceiveResult<T> {
433 match &self.0 {
434 GenericReceiverVariants::Ipc(receiver) => Ok(receiver.recv()?),
435 GenericReceiverVariants::Crossbeam(receiver) => {
436 let msg = receiver.recv()?;
438 Ok(msg.expect("Infallible"))
441 },
442 }
443 }
444
445 #[inline]
446 pub fn try_recv(&self) -> TryReceiveResult<T> {
447 match &self.0 {
448 GenericReceiverVariants::Ipc(receiver) => Ok(receiver.try_recv()?),
449 GenericReceiverVariants::Crossbeam(receiver) => {
450 let msg = receiver.try_recv()?;
451 Ok(msg.expect("Infallible"))
452 },
453 }
454 }
455
456 #[inline]
458 pub fn try_recv_timeout(&self, timeout: Duration) -> Result<T, TryReceiveError> {
459 match &self.0 {
460 GenericReceiverVariants::Ipc(ipc_receiver) => {
461 ipc_receiver.try_recv_timeout(timeout).map_err(|e| e.into())
462 },
463 GenericReceiverVariants::Crossbeam(receiver) => match receiver.recv_timeout(timeout) {
464 Ok(Ok(value)) => Ok(value),
465 Ok(Err(_)) => unreachable!("Infallable"),
466 Err(RecvTimeoutError::Disconnected) => {
467 Err(TryReceiveError::ReceiveError(ReceiveError::Disconnected))
468 },
469 Err(RecvTimeoutError::Timeout) => Err(TryReceiveError::Empty),
470 },
471 }
472 }
473
474 #[inline]
479 pub fn route_preserving_errors(self) -> RoutedReceiver<T>
480 where
481 T: Send + 'static,
482 {
483 match self.0 {
484 GenericReceiverVariants::Ipc(ipc_receiver) => {
485 let (crossbeam_sender, crossbeam_receiver) = crossbeam_channel::unbounded();
486 let crossbeam_sender_clone = crossbeam_sender;
487 ROUTER.add_typed_route(
488 ipc_receiver,
489 Box::new(move |message| {
490 let _ = crossbeam_sender_clone.send(message.map_err(|e| e.into()));
491 }),
492 );
493 crossbeam_receiver
494 },
495 GenericReceiverVariants::Crossbeam(receiver) => receiver,
496 }
497 }
498}
499
500impl<T> Serialize for GenericReceiver<T>
501where
502 T: for<'de> Deserialize<'de> + Serialize,
503{
504 fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
505 match &self.0 {
506 GenericReceiverVariants::Ipc(receiver) => {
507 s.serialize_newtype_variant("GenericReceiver", 0, "Ipc", receiver)
508 },
509 GenericReceiverVariants::Crossbeam(receiver) => {
510 if opts::get().multiprocess {
511 return Err(serde::ser::Error::custom(
512 "Crossbeam channel found in multiprocess mode!",
513 ));
514 } let receiver_clone_addr = Box::leak(Box::new(receiver.clone())) as *mut _ as usize;
517 s.serialize_newtype_variant("GenericReceiver", 1, "Crossbeam", &receiver_clone_addr)
518 },
519 }
520 }
521}
522
523struct GenericReceiverVisitor<T> {
524 marker: PhantomData<T>,
525}
526impl<'de, T> serde::de::Visitor<'de> for GenericReceiverVisitor<T>
527where
528 T: for<'a> Deserialize<'a> + Serialize,
529{
530 type Value = GenericReceiver<T>;
531
532 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
533 formatter.write_str("a GenericReceiver variant")
534 }
535
536 fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
537 where
538 A: serde::de::EnumAccess<'de>,
539 {
540 #[derive(Deserialize)]
541 enum GenericReceiverVariantNames {
542 Ipc,
543 Crossbeam,
544 }
545
546 let (variant_name, variant_data): (GenericReceiverVariantNames, _) = data.variant()?;
547
548 match variant_name {
549 GenericReceiverVariantNames::Ipc => variant_data
550 .newtype_variant::<ipc_channel::ipc::IpcReceiver<T>>()
551 .map(|receiver| GenericReceiver(GenericReceiverVariants::Ipc(receiver))),
552 GenericReceiverVariantNames::Crossbeam => {
553 if use_ipc() {
554 return Err(serde::de::Error::custom(
555 "Crossbeam channel found in multiprocess mode!",
556 ));
557 }
558 let addr = variant_data.newtype_variant::<usize>()?;
559 let ptr = addr as *mut RoutedReceiver<T>;
560 #[expect(unsafe_code)]
563 let receiver = unsafe { Box::from_raw(ptr) };
564 Ok(GenericReceiver(GenericReceiverVariants::Crossbeam(
565 *receiver,
566 )))
567 },
568 }
569 }
570}
571
572impl<'a, T> Deserialize<'a> for GenericReceiver<T>
573where
574 T: for<'de> Deserialize<'de> + Serialize,
575{
576 fn deserialize<D>(d: D) -> Result<GenericReceiver<T>, D::Error>
577 where
578 D: Deserializer<'a>,
579 {
580 d.deserialize_enum(
581 "GenericReceiver",
582 &["Ipc", "Crossbeam"],
583 GenericReceiverVisitor {
584 marker: PhantomData,
585 },
586 )
587 }
588}
589
590fn new_generic_channel_crossbeam<T>() -> (GenericSender<T>, GenericReceiver<T>)
594where
595 T: Serialize + for<'de> serde::Deserialize<'de>,
596{
597 let (tx, rx) = crossbeam_channel::unbounded();
598 (
599 GenericSender(GenericSenderVariants::Crossbeam(tx)),
600 GenericReceiver(GenericReceiverVariants::Crossbeam(rx)),
601 )
602}
603
604fn new_generic_channel_ipc<T>() -> Result<(GenericSender<T>, GenericReceiver<T>), std::io::Error>
605where
606 T: Serialize + for<'de> serde::Deserialize<'de>,
607{
608 ipc_channel::ipc::channel().map(|(tx, rx)| {
609 (
610 GenericSender(GenericSenderVariants::Ipc(tx)),
611 GenericReceiver(GenericReceiverVariants::Ipc(rx)),
612 )
613 })
614}
615
616pub fn channel<T>() -> Option<(GenericSender<T>, GenericReceiver<T>)>
620where
621 T: for<'de> Deserialize<'de> + Serialize,
622{
623 if use_ipc() {
624 new_generic_channel_ipc().ok()
625 } else {
626 Some(new_generic_channel_crossbeam())
627 }
628}
629
630#[cfg(test)]
631mod single_process_channel_tests {
632 use crate::generic_channel::{new_generic_channel_crossbeam, new_generic_channel_ipc};
637
638 #[test]
639 fn generic_crossbeam_can_send() {
640 let (tx, rx) = new_generic_channel_crossbeam();
641 tx.send(5).expect("Send failed");
642 let val = rx.recv().expect("Receive failed");
643 assert_eq!(val, 5);
644 }
645
646 #[test]
647 fn generic_crossbeam_ping_pong() {
648 let (tx, rx) = new_generic_channel_crossbeam();
649 let (tx2, rx2) = new_generic_channel_crossbeam();
650
651 tx.send(tx2).expect("Send failed");
652
653 std::thread::scope(|s| {
654 s.spawn(move || {
655 let reply_sender = rx.recv().expect("Receive failed");
656 reply_sender.send(42).expect("Sending reply failed");
657 });
658 });
659 let res = rx2.recv().expect("Receive of reply failed");
660 assert_eq!(res, 42);
661 }
662
663 #[test]
664 fn generic_ipc_ping_pong() {
665 let (tx, rx) = new_generic_channel_ipc().unwrap();
666 let (tx2, rx2) = new_generic_channel_ipc().unwrap();
667
668 tx.send(tx2).expect("Send failed");
669
670 std::thread::scope(|s| {
671 s.spawn(move || {
672 let reply_sender = rx.recv().expect("Receive failed");
673 reply_sender.send(42).expect("Sending reply failed");
674 });
675 });
676 let res = rx2.recv().expect("Receive of reply failed");
677 assert_eq!(res, 42);
678 }
679
680 #[test]
681 fn send_crossbeam_sender_over_ipc_channel() {
682 let (tx, rx) = new_generic_channel_ipc().unwrap();
683 let (tx2, rx2) = new_generic_channel_crossbeam();
684
685 tx.send(tx2).expect("Send failed");
686
687 std::thread::scope(|s| {
688 s.spawn(move || {
689 let reply_sender = rx.recv().expect("Receive failed");
690 reply_sender.send(42).expect("Sending reply failed");
691 });
692 });
693 let res = rx2.recv().expect("Receive of reply failed");
694 assert_eq!(res, 42);
695 }
696
697 #[test]
698 fn send_generic_ipc_channel_over_crossbeam() {
699 let (tx, rx) = new_generic_channel_crossbeam();
700 let (tx2, rx2) = new_generic_channel_ipc().unwrap();
701
702 tx.send(tx2).expect("Send failed");
703
704 std::thread::scope(|s| {
705 s.spawn(move || {
706 let reply_sender = rx.recv().expect("Receive failed");
707 reply_sender.send(42).expect("Sending reply failed");
708 });
709 });
710 let res = rx2.recv().expect("Receive of reply failed");
711 assert_eq!(res, 42);
712 }
713
714 #[test]
715 fn send_crossbeam_receiver_over_ipc_channel() {
716 let (tx, rx) = new_generic_channel_ipc().unwrap();
717 let (tx2, rx2) = new_generic_channel_crossbeam();
718
719 tx.send(rx2).expect("Send failed");
720 tx2.send(42).expect("Send failed");
721
722 std::thread::scope(|s| {
723 s.spawn(move || {
724 let another_receiver = rx.recv().expect("Receive failed");
725 let res = another_receiver.recv().expect("Receive failed");
726 assert_eq!(res, 42);
727 });
728 });
729 }
730
731 #[test]
732 fn test_timeout_ipc() {
733 let (tx, rx) = new_generic_channel_ipc().unwrap();
734 let timeout_duration = std::time::Duration::from_secs(3);
735 std::thread::spawn(move || {
736 std::thread::sleep(timeout_duration - std::time::Duration::from_secs(1));
737 assert!(tx.send(()).is_ok());
738 });
739 let received = rx.try_recv_timeout(timeout_duration);
740 assert!(received.is_ok());
741 }
742
743 #[test]
744 fn test_timeout_crossbeam() {
745 let (tx, rx) = new_generic_channel_crossbeam();
746 let timeout_duration = std::time::Duration::from_secs(3);
747 std::thread::spawn(move || {
748 std::thread::sleep(timeout_duration - std::time::Duration::from_secs(1));
749 assert!(tx.send(()).is_ok());
750 });
751 let received = rx.try_recv_timeout(timeout_duration);
752 assert!(received.is_ok());
753 }
754}
755
756#[cfg(test)]
758mod generic_receiversets_tests {
759 use std::time::Duration;
760
761 use crate::generic_channel::generic_channelset::{
762 GenericSelectionResult, create_crossbeam_receiver_set, create_ipc_receiver_set,
763 };
764 use crate::generic_channel::{new_generic_channel_crossbeam, new_generic_channel_ipc};
765
766 #[test]
767 fn test_ipc_side1() {
768 let (snd1, recv1) = new_generic_channel_ipc().unwrap();
769 let (snd2, recv2) = new_generic_channel_ipc().unwrap();
770
771 let snd1_c = snd1.clone();
773 let snd2_c = snd2.clone();
774 let mut set = create_ipc_receiver_set();
775 let recv1_select_index = set.add(recv1);
776 let _recv2_select_index = set.add(recv2);
777
778 std::thread::spawn(move || {
779 snd1_c.send(10).unwrap();
780 });
781 std::thread::spawn(move || {
782 std::thread::sleep(Duration::from_secs(1));
783 let _ = snd2_c.send(20); });
785
786 let select_result = set.select();
787 let channel_result = select_result.first().unwrap();
788 assert_eq!(
789 *channel_result,
790 GenericSelectionResult::MessageReceived(recv1_select_index, 10)
791 );
792 }
793
794 #[test]
795 fn test_ipc_side2() {
796 let (snd1, recv1) = new_generic_channel_ipc().unwrap();
797 let (snd2, recv2) = new_generic_channel_ipc().unwrap();
798
799 let snd1_c = snd1.clone();
801 let snd2_c = snd2.clone();
802 let mut set = create_ipc_receiver_set();
803 let _recv1_select_index = set.add(recv1);
804 let recv2_select_index = set.add(recv2);
805
806 std::thread::spawn(move || {
807 std::thread::sleep(Duration::from_secs(1));
808 let _ = snd1_c.send(10);
809 });
810 std::thread::spawn(move || {
811 snd2_c.send(20).unwrap();
812 });
813
814 let select_result = set.select();
815 let channel_result = select_result.first().unwrap();
816 assert_eq!(
817 *channel_result,
818 GenericSelectionResult::MessageReceived(recv2_select_index, 20)
819 );
820 }
821
822 #[test]
823 fn test_crossbeam_side1() {
824 let (snd1, recv1) = new_generic_channel_crossbeam();
825 let (snd2, recv2) = new_generic_channel_crossbeam();
826
827 let snd1_c = snd1.clone();
829 let snd2_c = snd2.clone();
830 let mut set = create_crossbeam_receiver_set();
831 let recv1_select_index = set.add(recv1);
832 let _recv2_select_index = set.add(recv2);
833
834 std::thread::spawn(move || {
835 snd1_c.send(10).unwrap();
836 });
837 std::thread::spawn(move || {
838 std::thread::sleep(Duration::from_secs(2));
839 let _ = snd2_c.send(20);
840 });
841
842 let select_result = set.select();
843 let channel_result = select_result.first().unwrap();
844 assert_eq!(
845 *channel_result,
846 GenericSelectionResult::MessageReceived(recv1_select_index, 10)
847 );
848 }
849
850 #[test]
851 fn test_crossbeam_side2() {
852 let (snd1, recv1) = new_generic_channel_crossbeam();
853 let (snd2, recv2) = new_generic_channel_crossbeam();
854
855 let snd1_c = snd1.clone();
857 let snd2_c = snd2.clone();
858 let mut set = create_crossbeam_receiver_set();
859 let _recv1_select_index = set.add(recv1);
860 let recv2_select_index = set.add(recv2);
861
862 std::thread::spawn(move || {
863 std::thread::sleep(Duration::from_secs(2));
864 let _ = snd1_c.send(10);
865 });
866 std::thread::spawn(move || {
867 snd2_c.send(20).unwrap();
868 });
869
870 let select_result = set.select();
871 let channel_result = select_result.first().unwrap();
872 assert_eq!(
873 *channel_result,
874 GenericSelectionResult::MessageReceived(recv2_select_index, 20)
875 );
876 }
877
878 #[test]
879 fn test_ipc_no_crash_on_disconnect() {
880 let (snd1, recv1) = new_generic_channel_ipc().unwrap();
883 let (snd2, recv2) = new_generic_channel_ipc().unwrap();
884
885 let snd1_c = snd1.clone();
887 let mut set = create_ipc_receiver_set();
888 let _recv1_select_index = set.add(recv1);
889 let recv2_select_index = set.add(recv2);
890
891 std::thread::spawn(move || {
892 std::thread::sleep(Duration::from_secs(2));
893 let _ = snd1_c.send(10);
894 });
895 std::thread::spawn(move || {
896 snd2.send(20).unwrap();
897 });
898 std::thread::sleep(Duration::from_secs(1));
899 let select_result = set.select();
900 let channel_result = select_result.first().unwrap();
901 assert_eq!(
902 *channel_result,
903 GenericSelectionResult::MessageReceived(recv2_select_index, 20)
904 );
905 }
906
907 #[test]
908 fn test_crossbeam_no_crash_on_disconnect() {
909 let (snd1, recv1) = new_generic_channel_crossbeam();
911 let (snd2, recv2) = new_generic_channel_crossbeam();
912
913 let snd1_c = snd1.clone();
915 let mut set = create_crossbeam_receiver_set();
916 let _recv1_select_index = set.add(recv1);
917 let recv2_select_index = set.add(recv2);
918
919 std::thread::spawn(move || {
920 std::thread::sleep(Duration::from_secs(2));
921 let _ = snd1_c.send(10);
922 });
923 std::thread::spawn(move || {
924 snd2.send(20).unwrap();
925 });
926 std::thread::sleep(Duration::from_secs(1));
927 let select_result = set.select();
928 let channel_result = select_result.first().unwrap();
929 assert_eq!(
930 *channel_result,
931 GenericSelectionResult::MessageReceived(recv2_select_index, 20)
932 );
933 }
934
935 #[test]
936 fn test_ipc_disconnect_correct_message() {
937 let (snd1, recv1) = new_generic_channel_ipc().unwrap();
939 let (snd2, recv2) = new_generic_channel_ipc().unwrap();
940
941 let snd1_c = snd1.clone();
943 let mut set = create_ipc_receiver_set();
944 let _recv1_select_index = set.add(recv1);
945 let recv2_select_index = set.add(recv2);
946
947 std::thread::spawn(move || {
948 std::thread::sleep(Duration::from_secs(2));
949 let _ = snd1_c.send(10);
950 });
951 std::thread::spawn(move || {
952 drop(snd2);
953 });
954
955 let select_result = set.select();
956 let channel_result = select_result.first().unwrap();
957 assert_eq!(
958 *channel_result,
959 GenericSelectionResult::ChannelClosed(recv2_select_index)
960 );
961 }
962
963 #[test]
964 fn test_crossbeam_disconnect_correct_messaget() {
965 let (snd1, recv1) = new_generic_channel_crossbeam();
966 let (snd2, recv2) = new_generic_channel_crossbeam();
967
968 let snd1_c = snd1.clone();
970 let mut set = create_crossbeam_receiver_set();
971 let _recv1_select_index = set.add(recv1);
972 let recv2_select_index = set.add(recv2);
973
974 std::thread::spawn(move || {
975 std::thread::sleep(Duration::from_secs(2));
976 let _ = snd1_c.send(10);
977 });
978 std::thread::spawn(move || {
979 drop(snd2);
980 });
981
982 let select_result = set.select();
983 let channel_result = select_result.first().unwrap();
984 assert_eq!(
985 *channel_result,
986 GenericSelectionResult::ChannelClosed(recv2_select_index)
987 );
988 }
989}