Repository: servo/servo
File: components/constellation/constellation.rs (Rust)

Code before:
// or returns after printing a warning.
macro_rules! maybe_pipeline {
    ($this:ident, $bc_id:ident, $warn_msg:expr) => {
        match $this.browsing_contexts.get(&$bc_id) {
            Some(ctx) => ctx.pipeline_id,
            None => return warn!("{}: {}", $bc_id, $warn_msg),
        }
    };
}

// Helper macro that sends a message to the event loop of a given pipeline
// or returns after printing a warning.
macro_rules! maybe_send {
    ($this:ident, $pipeline_id:ident, $msg:expr, $warn_msg:expr) => {
        let result = match $this.pipelines.get(&$pipeline_id) {
            Some(pipeline) => pipeline.event_loop.send($msg),
            None => {
                return warn!("{}: {}", $pipeline_id, $warn_msg);
            },
        };
        if let Err(e) = result {
            $this.handle_send_error($pipeline_id, e);
        }
    };
}

/// The `Constellation` itself. In the servo browser, there is one
/// constellation, which maintains all of the browser global data.
/// In embedded applications, there may be more than one constellation,
/// which are independent of each other.
///
/// The constellation may be in a different process from the pipelines,
/// and communicates using IPC.
///
/// It is parameterized over a `LayoutThreadFactory` and a
/// `ScriptThreadFactory` (which in practice are implemented by
/// `LayoutThread` in the `layout` crate, and `ScriptThread` in
/// the `script` crate). Script and layout communicate using a `Message`
/// type.
pub struct Constellation<STF, SWF> {
    /// An ipc-sender/threaded-receiver pair
    /// to facilitate installing pipeline namespaces in threads
    /// via a per-process installer.
    namespace_receiver: Receiver<Result<PipelineNamespaceRequest, IpcError>>,
    namespace_ipc_sender: IpcSender<PipelineNamespaceRequest>,

    /// An IPC channel for script threads to send messages to the constellation.
    /// This is the script threads' view of `script_receiver`.
    script_sender: IpcSender<(PipelineId, FromScriptMsg)>,

    /// A channel for the constellation to receive messages from script threads.

Review comment (bug):
I think we should avoid metaprogramming for these type of helpers. Please remove these or convert them into functions. I think also that `maybe_send` isn't very descriptive of what happens in a failure case. I would call them something like "send_handling_error" or something along those lines.

Code after:
/// The `Constellation` itself. In the servo browser, there is one
/// constellation, which maintains all of the browser global data.
/// In embedded applications, there may be more than one constellation,
/// which are independent of each other.
///
/// The constellation may be in a different process from the pipelines,
/// and communicates using IPC.
///
/// It is parameterized over a `LayoutThreadFactory` and a
/// `ScriptThreadFactory` (which in practice are implemented by
/// `LayoutThread` in the `layout` crate, and `ScriptThread` in
/// the `script` crate). Script and layout communicate using a `Message`
/// type.
pub struct Constellation<STF, SWF> {
    /// An ipc-sender/threaded-receiver pair
    /// to facilitate installing pipeline namespaces in threads
    /// via a per-process installer.
    namespace_receiver: RoutedReceiver<PipelineNamespaceRequest>,
    namespace_ipc_sender: GenericSender<PipelineNamespaceRequest>,

    /// An IPC channel for script threads to send messages to the constellation.
    /// This is the script threads' view of `script_receiver`.
    script_sender: GenericSender<(WebViewId, PipelineId, ScriptToConstellationMessage)>,

    /// A channel for the constellation to receive messages from script threads.
    /// This is the constellation's view of `script_sender`.
    script_receiver:
        Receiver<Result<(WebViewId, PipelineId, ScriptToConstellationMessage), IpcError>>,

    /// A handle to register components for hang monitoring.
    /// None when in multiprocess mode.
    background_monitor_register: Option<Box<dyn BackgroundHangMonitorRegister>>,

    /// In single process mode, a join handle on the BHM worker thread.
    background_monitor_register_join_handle: Option<JoinHandle<()>>,

    /// Channels to control all background-hang monitors.
    /// TODO: store them on the relevant BrowsingContextGroup,
    /// so that they could be controlled on a "per-tab/event-loop" basis.
    background_monitor_control_senders: Vec<GenericSender<BackgroundHangMonitorControlMsg>>,

    /// A channel for the background hang monitor to send messages
    /// to the constellation.
    background_hang_monitor_sender: GenericSender<HangMonitorAlert>,

    /// A channel for the constellation to receiver messages
    /// from the background hang monitor.
    background_hang_monitor_receiver: RoutedReceiver<HangMonitorAlert>,

    /// A factory for creating layouts. This allows customizing the kind
    /// of layout created for a [`Constellation`] and prevents a circular crate