use std::cell::RefCell;
use crossbeam_channel::{Receiver, Sender, TryRecvError, unbounded};
use log::warn;
use serde::Serialize;
use servo_base::generic_channel::{GenericSender, SendError, SendResult};
use tokio::sync::mpsc::UnboundedSender as TokioSender;
use tokio::sync::oneshot::Sender as TokioOneshotSender;
use crate::ServoError;
pub(crate) struct ServoErrorSender {
sender: Sender<ServoError>,
}
impl ServoErrorSender {
pub(crate) fn raise_response_send_error(&self, error: SendError) {
if let Err(error) = self.sender.send(ServoError::ResponseFailedToSend(error)) {
warn!("Failed to send Servo error: {error:?}");
}
}
}
pub(crate) struct ServoErrorChannel {
sender: Sender<ServoError>,
receiver: Receiver<ServoError>,
}
impl Default for ServoErrorChannel {
fn default() -> Self {
let (sender, receiver) = unbounded();
Self { sender, receiver }
}
}
impl ServoErrorChannel {
pub(crate) fn sender(&self) -> ServoErrorSender {
ServoErrorSender {
sender: self.sender.clone(),
}
}
pub(crate) fn try_recv(&self) -> Option<ServoError> {
match self.receiver.try_recv() {
Ok(result) => Some(result),
Err(error) => {
debug_assert_eq!(error, TryRecvError::Empty);
None
},
}
}
}
pub(crate) trait AbstractSender {
type Message;
fn send(&self, value: Self::Message) -> SendResult;
}
impl<T: Serialize> AbstractSender for GenericSender<T> {
type Message = T;
fn send(&self, value: T) -> SendResult {
GenericSender::send(self, value)
}
}
impl<T> AbstractSender for TokioSender<T> {
type Message = T;
fn send(&self, value: T) -> SendResult {
TokioSender::send(self, value).map_err(|_| SendError::Disconnected)
}
}
pub(crate) struct OneshotSender<T>(RefCell<Option<TokioOneshotSender<T>>>);
impl<T> From<TokioOneshotSender<T>> for OneshotSender<T> {
fn from(sender: TokioOneshotSender<T>) -> Self {
Self(RefCell::new(Some(sender)))
}
}
impl<T> AbstractSender for OneshotSender<T> {
type Message = T;
fn send(&self, value: T) -> SendResult {
let sender = self.0.borrow_mut().take();
if let Some(sender) = sender {
TokioOneshotSender::send(sender, value).map_err(|_| SendError::Disconnected)
} else {
Err(SendError::Disconnected)
}
}
}
pub(crate) struct IpcResponder<T> {
response_sender: Box<dyn AbstractSender<Message = T>>,
response_sent: bool,
default_response: Option<T>,
}
impl<T: Serialize + 'static> IpcResponder<T> {
pub(crate) fn new(response_sender: GenericSender<T>, default_response: T) -> Self {
Self {
response_sender: Box::new(response_sender),
response_sent: false,
default_response: Some(default_response),
}
}
}
impl<T: 'static> IpcResponder<T> {
pub(crate) fn new_same_process(
response_sender: Box<dyn AbstractSender<Message = T>>,
default_response: T,
) -> Self {
Self {
response_sender,
response_sent: false,
default_response: Some(default_response),
}
}
}
impl<T> IpcResponder<T> {
pub(crate) fn send(&mut self, response: T) -> SendResult {
let result = self.response_sender.send(response);
self.response_sent = true;
result
}
}
impl<T> Drop for IpcResponder<T> {
fn drop(&mut self) {
if !self.response_sent {
let response = self
.default_response
.take()
.expect("Guaranteed by inherent impl");
let _ = self.response_sender.send(response);
}
}
}