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