/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ extern crate crossbeam_channel; extern crate ipc_channel; extern crate serde; pub mod base_channel { pub use crossbeam_channel::*; } // Needed to re-export the select macro. pub use crossbeam_channel::*; use ipc_channel::ipc::IpcReceiver; use ipc_channel::router::ROUTER; use serde::{Deserialize, Serialize}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; pub fn route_ipc_receiver_to_new_servo_receiver(ipc_receiver: IpcReceiver) -> Receiver where T: for<'de> Deserialize<'de> + Serialize + Send + 'static { let (servo_sender, servo_receiver) = channel(); ROUTER.add_route( ipc_receiver.to_opaque(), Box::new(move |message| { drop(servo_sender.send(message.to::().unwrap())) }), ); servo_receiver } pub fn route_ipc_receiver_to_new_servo_sender(ipc_receiver: IpcReceiver, servo_sender: Sender) where T: for<'de> Deserialize<'de> + Serialize + Send + 'static { ROUTER.add_route( ipc_receiver.to_opaque(), Box::new(move |message| { drop(servo_sender.send(message.to::().unwrap())) }), ) } pub fn channel() -> (Sender, Receiver) { let (base_sender, base_receiver) = crossbeam_channel::unbounded::(); let is_disconnected = Arc::new(AtomicBool::new(false)); (Sender::new(base_sender, is_disconnected.clone()), Receiver::new(base_receiver, is_disconnected)) } #[derive(Debug, PartialEq)] pub enum ChannelError { ChannelClosedError } pub struct Receiver { receiver: crossbeam_channel::Receiver, is_disconnected: Arc, } impl Drop for Receiver { fn drop(&mut self) { self.is_disconnected.store(true, Ordering::SeqCst); } } impl Clone for Receiver { fn clone(&self) -> Self { Receiver { receiver: self.receiver.clone(), is_disconnected: self.is_disconnected.clone(), } } } impl Receiver { pub fn new(receiver: crossbeam_channel::Receiver, is_disconnected: Arc) -> Receiver { Receiver { receiver, is_disconnected, } } pub fn recv(&self) -> Option { self.receiver.recv() } pub fn try_recv(&self) -> Option { self.receiver.try_recv() } pub fn len(&self) -> usize { self.receiver.len() } pub fn select(&self) -> &crossbeam_channel::Receiver { &self.receiver } } impl Iterator for Receiver { type Item = T; fn next(&mut self) -> Option { self.receiver.recv() } } impl<'a, T> IntoIterator for &'a Receiver { type Item = T; type IntoIter = crossbeam_channel::Receiver; fn into_iter(self) -> Self::IntoIter { self.receiver.clone() } } pub struct Sender { sender: crossbeam_channel::Sender, is_disconnected: Arc, } impl Clone for Sender { fn clone(&self) -> Self { Sender { sender: self.sender.clone(), is_disconnected: self.is_disconnected.clone(), } } } impl Sender { pub fn new(sender: crossbeam_channel::Sender, is_disconnected: Arc) -> Sender { Sender { sender, is_disconnected, } } pub fn send(&self, msg: T) -> Result<(), ChannelError> { if self.is_disconnected.load(Ordering::SeqCst) { Err(ChannelError::ChannelClosedError) } else { Ok(self.sender.send(msg)) } } pub fn len(&self) -> usize { self.sender.len() } pub fn select(&self) -> Option<&crossbeam_channel::Sender> { if self.is_disconnected.load(Ordering::SeqCst) { None } else { Some(&self.sender) } } }