constellation/
event_loop.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! This module contains the `EventLoop` type, which is the constellation's
6//! view of a script thread. When an `EventLoop` is dropped, an `ExitScriptThread`
7//! message is sent to the script thread, asking it to shut down.
8
9use std::hash::Hash;
10use std::marker::PhantomData;
11use std::rc::Rc;
12use std::sync::atomic::{AtomicUsize, Ordering};
13
14use background_hang_monitor_api::{BackgroundHangMonitorControlMsg, HangMonitorAlert};
15use base::generic_channel::{GenericReceiver, GenericSender};
16use ipc_channel::Error;
17use ipc_channel::ipc::IpcSender;
18use script_traits::{InitialScriptState, NewPipelineInfo, ScriptThreadMessage};
19use serde::{Deserialize, Serialize};
20use servo_config::opts::Opts;
21use servo_config::prefs::Preferences;
22
23static CURRENT_EVENT_LOOP_ID: AtomicUsize = AtomicUsize::new(0);
24
25/// <https://html.spec.whatwg.org/multipage/#event-loop>
26pub struct EventLoop {
27    script_chan: GenericSender<ScriptThreadMessage>,
28    dont_send_or_sync: PhantomData<Rc<()>>,
29    id: usize,
30}
31
32impl PartialEq for EventLoop {
33    fn eq(&self, other: &Self) -> bool {
34        self.id == other.id
35    }
36}
37
38impl Eq for EventLoop {}
39
40impl Hash for EventLoop {
41    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
42        self.id.hash(state);
43    }
44}
45
46impl Drop for EventLoop {
47    fn drop(&mut self) {
48        let _ = self.script_chan.send(ScriptThreadMessage::ExitScriptThread);
49    }
50}
51
52impl EventLoop {
53    /// Create a new event loop from the channel to its script thread.
54    pub fn new(script_chan: GenericSender<ScriptThreadMessage>) -> Rc<EventLoop> {
55        let id = CURRENT_EVENT_LOOP_ID.fetch_add(1, Ordering::Relaxed);
56        Rc::new(EventLoop {
57            script_chan,
58            dont_send_or_sync: PhantomData,
59            id,
60        })
61    }
62
63    /// Send a message to the event loop.
64    pub fn send(&self, msg: ScriptThreadMessage) -> Result<(), Error> {
65        self.script_chan
66            .send(msg)
67            .map_err(|_err| Box::new(ipc_channel::ErrorKind::Custom("SendError".into())))
68    }
69}
70
71/// All of the information necessary to create a new script [`EventLoop`] in a new process.
72#[derive(Deserialize, Serialize)]
73pub struct NewScriptEventLoopProcessInfo {
74    pub new_pipeline_info: NewPipelineInfo,
75    pub initial_script_state: InitialScriptState,
76    pub constellation_to_bhm_receiver: GenericReceiver<BackgroundHangMonitorControlMsg>,
77    pub bhm_to_constellation_sender: GenericSender<HangMonitorAlert>,
78    pub lifeline_sender: IpcSender<()>,
79    pub opts: Opts,
80    pub prefs: Box<Preferences>,
81    /// The broken image icon data that is used to create an image to show in place of broken images.
82    pub broken_image_icon_data: Vec<u8>,
83}