mirror of
https://github.com/servo/servo.git
synced 2025-09-29 16:19:14 +01:00
GenericChannel: Migrate compositor channels to GenericChannel (#38782)
Besides migrating the channel to GenericChannel, this PR adds `routed_channel_with_local_sender()` to `generic_channel`. This is for existing use-cases, where we want to provide both an IPC capable GenericSender, as well as a crossbeam Sender, for efficient sending if the sender is in the same process. Testing: All of our channels should send / receive at least some messages during WPT tests. Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
parent
7441944e36
commit
fb1c0a4c48
9 changed files with 98 additions and 43 deletions
|
@ -395,6 +395,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A GenericChannel, which was routed via the Router.
|
||||
pub struct GenericRoutedChannel<T: Serialize + for<'de> Deserialize<'de>> {
|
||||
/// A GenericSender of the channel, i.e. it may be sent to other processes in multiprocess mode.
|
||||
/// Connected to `local_receiver` via the [ROUTER].
|
||||
pub generic_sender: GenericSender<T>,
|
||||
/// A sender that directly sends to the local_receiver. Can only be used in the same process
|
||||
/// as the `local_receiver`.
|
||||
pub local_sender: crossbeam_channel::Sender<Result<T, ipc_channel::Error>>,
|
||||
/// The receiving end of the channel. Only usable in the current process.
|
||||
pub local_receiver: RoutedReceiver<T>,
|
||||
}
|
||||
|
||||
/// Private helper function to create a crossbeam based channel.
|
||||
///
|
||||
/// Do NOT make this function public!
|
||||
|
@ -435,6 +447,34 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a [GenericRoutedChannel], where the receiver is usable in the current process,
|
||||
/// and sending is possible both in remote and local process, via the generic_sender and the
|
||||
/// local_sender.
|
||||
pub fn routed_channel_with_local_sender<T>() -> Option<GenericRoutedChannel<T>>
|
||||
where
|
||||
T: for<'de> Deserialize<'de> + Serialize + Send + 'static,
|
||||
{
|
||||
let (crossbeam_sender, crossbeam_receiver) = crossbeam_channel::unbounded();
|
||||
let generic_sender = if opts::get().multiprocess || opts::get().force_ipc {
|
||||
let (ipc_sender, ipc_receiver) = ipc_channel::ipc::channel().ok()?;
|
||||
let crossbeam_sender_clone = crossbeam_sender.clone();
|
||||
ROUTER.add_typed_route(
|
||||
ipc_receiver,
|
||||
Box::new(move |message| {
|
||||
let _ = crossbeam_sender_clone.send(message);
|
||||
}),
|
||||
);
|
||||
GenericSender(GenericSenderVariants::Ipc(ipc_sender))
|
||||
} else {
|
||||
GenericSender(GenericSenderVariants::Crossbeam(crossbeam_sender.clone()))
|
||||
};
|
||||
Some(GenericRoutedChannel {
|
||||
generic_sender,
|
||||
local_sender: crossbeam_sender,
|
||||
local_receiver: crossbeam_receiver,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod single_process_channel_tests {
|
||||
//! These unit-tests test that ipc_channel and crossbeam_channel Senders and Receivers
|
||||
|
|
|
@ -23,6 +23,7 @@ pub mod viewport_description;
|
|||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use base::generic_channel::GenericSender;
|
||||
use bitflags::bitflags;
|
||||
use display_list::CompositorDisplayListInfo;
|
||||
use embedder_traits::ScreenGeometry;
|
||||
|
@ -44,7 +45,12 @@ use crate::viewport_description::ViewportDescription;
|
|||
/// Sends messages to the compositor.
|
||||
#[derive(Clone)]
|
||||
pub struct CompositorProxy {
|
||||
pub sender: Sender<CompositorMsg>,
|
||||
/// A sender optimised for sending in the local process.
|
||||
/// The type is a Result to match the API of ipc_channel after routing,
|
||||
/// which contains a Result to propagate deserialization errors to the
|
||||
/// recipient.
|
||||
/// The field is private to hide the inner `Result` type.
|
||||
sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
|
||||
/// Access to [`Self::sender`] that is possible to send across an IPC
|
||||
/// channel. These messages are routed via the router thread to
|
||||
/// [`Self::sender`].
|
||||
|
@ -52,6 +58,20 @@ pub struct CompositorProxy {
|
|||
pub event_loop_waker: Box<dyn EventLoopWaker>,
|
||||
}
|
||||
|
||||
impl CompositorProxy {
|
||||
pub fn new(
|
||||
local_process_sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
|
||||
cross_process_compositor_api: CrossProcessCompositorApi,
|
||||
event_loop_waker: Box<dyn EventLoopWaker>,
|
||||
) -> Self {
|
||||
Self {
|
||||
sender: local_process_sender,
|
||||
cross_process_compositor_api,
|
||||
event_loop_waker,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpaqueSender<CompositorMsg> for CompositorProxy {
|
||||
fn send(&self, message: CompositorMsg) {
|
||||
CompositorProxy::send(self, message)
|
||||
|
@ -60,7 +80,7 @@ impl OpaqueSender<CompositorMsg> for CompositorProxy {
|
|||
|
||||
impl CompositorProxy {
|
||||
pub fn send(&self, msg: CompositorMsg) {
|
||||
if let Err(err) = self.sender.send(msg) {
|
||||
if let Err(err) = self.sender.send(Ok(msg)) {
|
||||
warn!("Failed to send response ({:?}).", err);
|
||||
}
|
||||
self.event_loop_waker.wake();
|
||||
|
@ -170,18 +190,18 @@ pub struct CompositionPipeline {
|
|||
|
||||
/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
|
||||
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct CrossProcessCompositorApi(pub IpcSender<CompositorMsg>);
|
||||
pub struct CrossProcessCompositorApi(pub GenericSender<CompositorMsg>);
|
||||
|
||||
impl CrossProcessCompositorApi {
|
||||
/// Create a new [`CrossProcessCompositorApi`] struct that does not have a listener on the other
|
||||
/// end to use for unit testing.
|
||||
pub fn dummy() -> Self {
|
||||
let (sender, _) = ipc::channel().unwrap();
|
||||
let (sender, _) = base::generic_channel::channel().unwrap();
|
||||
Self(sender)
|
||||
}
|
||||
|
||||
/// Get the sender for this proxy.
|
||||
pub fn sender(&self) -> &IpcSender<CompositorMsg> {
|
||||
pub fn sender(&self) -> &GenericSender<CompositorMsg> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::collections::HashMap;
|
|||
use std::fmt;
|
||||
|
||||
use base::Epoch;
|
||||
use base::generic_channel::{GenericSender, SendResult};
|
||||
use base::id::{
|
||||
BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId,
|
||||
MessagePortRouterId, PipelineId, ServiceWorkerId, ServiceWorkerRegistrationId, WebViewId,
|
||||
|
@ -21,7 +22,6 @@ use embedder_traits::{
|
|||
};
|
||||
use euclid::default::Size2D as UntypedSize2D;
|
||||
use http::{HeaderMap, Method};
|
||||
use ipc_channel::Error as IpcError;
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use net_traits::policy_container::PolicyContainer;
|
||||
|
@ -46,14 +46,14 @@ use crate::{
|
|||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct ScriptToConstellationChan {
|
||||
/// Sender for communicating with constellation thread.
|
||||
pub sender: IpcSender<(PipelineId, ScriptToConstellationMessage)>,
|
||||
pub sender: GenericSender<(PipelineId, ScriptToConstellationMessage)>,
|
||||
/// Used to identify the origin of the message.
|
||||
pub pipeline_id: PipelineId,
|
||||
}
|
||||
|
||||
impl ScriptToConstellationChan {
|
||||
/// Send ScriptMsg and attach the pipeline_id to the message.
|
||||
pub fn send(&self, msg: ScriptToConstellationMessage) -> Result<(), IpcError> {
|
||||
pub fn send(&self, msg: ScriptToConstellationMessage) -> SendResult {
|
||||
self.sender.send((self.pipeline_id, msg))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue