Skip to content

Commit

Permalink
Script thread lifetime is now managed by the constellation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Jeffrey authored and notriddle committed Nov 9, 2016
1 parent d1b7f19 commit 0e7ffaf
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 22 deletions.
27 changes: 26 additions & 1 deletion components/constellation/constellation.rs
Expand Up @@ -53,6 +53,7 @@ use std::iter::once;
use std::marker::PhantomData;
use std::mem::replace;
use std::process;
use std::rc::Rc;
use std::sync::Arc;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::thread;
Expand Down Expand Up @@ -365,6 +366,30 @@ enum ExitPipelineMode {
Force,
}

/// A script channel, that closes the script thread down when it is dropped
pub struct ScriptChan {
chan: IpcSender<ConstellationControlMsg>,
dont_send_or_sync: PhantomData<Rc<()>>,
}

impl Drop for ScriptChan {
fn drop(&mut self) {
let _ = self.chan.send(ConstellationControlMsg::ExitScriptThread);
}
}

impl ScriptChan {
pub fn send(&self, msg: ConstellationControlMsg) -> Result<(), IOError> {
self.chan.send(msg)
}
pub fn new(chan: IpcSender<ConstellationControlMsg>) -> Rc<ScriptChan> {
Rc::new(ScriptChan { chan: chan, dont_send_or_sync: PhantomData })
}
pub fn sender(&self) -> IpcSender<ConstellationControlMsg> {
self.chan.clone()
}
}

/// A logger directed at the constellation from content processes
#[derive(Clone)]
pub struct FromScriptLogger {
Expand Down Expand Up @@ -561,7 +586,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
parent_info: Option<(PipelineId, FrameType)>,
old_pipeline_id: Option<PipelineId>,
initial_window_size: Option<TypedSize2D<f32, PagePx>>,
script_channel: Option<IpcSender<ConstellationControlMsg>>,
script_channel: Option<Rc<ScriptChan>>,
load_data: LoadData,
is_private: bool) {
if self.shutting_down { return; }
Expand Down
14 changes: 8 additions & 6 deletions components/constellation/pipeline.rs
Expand Up @@ -6,6 +6,7 @@ use bluetooth_traits::BluetoothRequest;
use compositing::CompositionPipeline;
use compositing::CompositorProxy;
use compositing::compositor_thread::Msg as CompositorMsg;
use constellation::ScriptChan;
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
use euclid::scale_factor::ScaleFactor;
use euclid::size::TypedSize2D;
Expand All @@ -30,6 +31,7 @@ use std::env;
use std::ffi::OsStr;
use std::io::Error as IOError;
use std::process;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use style_traits::{PagePx, ViewportPx};
use url::Url;
Expand All @@ -50,7 +52,7 @@ pub struct Pipeline {
/// The ID of the frame that contains this Pipeline.
pub frame_id: FrameId,
pub parent_info: Option<(PipelineId, FrameType)>,
pub script_chan: IpcSender<ConstellationControlMsg>,
pub script_chan: Rc<ScriptChan>,
/// A channel to layout, for performing reflows and shutdown.
pub layout_chan: IpcSender<LayoutControlMsg>,
/// A channel to the compositor.
Expand Down Expand Up @@ -113,7 +115,7 @@ pub struct InitialPipelineState {
pub device_pixel_ratio: ScaleFactor<f32, ViewportPx, DevicePixel>,
/// A channel to the script thread, if applicable. If this is `Some`,
/// then `parent_info` must also be `Some`.
pub script_chan: Option<IpcSender<ConstellationControlMsg>>,
pub script_chan: Option<Rc<ScriptChan>>,
/// Information about the page to load.
pub load_data: LoadData,
/// The ID of the pipeline namespace for this script thread.
Expand Down Expand Up @@ -165,7 +167,7 @@ impl Pipeline {
}
None => {
let (script_chan, script_port) = ipc::channel().expect("Pipeline script chan");
(script_chan, Some((script_port, pipeline_port)))
(ScriptChan::new(script_chan), Some((script_port, pipeline_port)))
}
};

Expand Down Expand Up @@ -215,7 +217,7 @@ impl Pipeline {
mem_profiler_chan: state.mem_profiler_chan,
window_size: window_size,
layout_to_constellation_chan: state.layout_to_constellation_chan,
script_chan: script_chan.clone(),
script_chan: script_chan.sender(),
load_data: state.load_data.clone(),
script_port: script_port,
opts: (*opts::get()).clone(),
Expand Down Expand Up @@ -258,7 +260,7 @@ impl Pipeline {
fn new(id: PipelineId,
frame_id: FrameId,
parent_info: Option<(PipelineId, FrameType)>,
script_chan: IpcSender<ConstellationControlMsg>,
script_chan: Rc<ScriptChan>,
layout_chan: IpcSender<LayoutControlMsg>,
compositor_proxy: Box<CompositorProxy + 'static + Send>,
is_private: bool,
Expand Down Expand Up @@ -329,7 +331,7 @@ impl Pipeline {
pub fn to_sendable(&self) -> CompositionPipeline {
CompositionPipeline {
id: self.id.clone(),
script_chan: self.script_chan.clone(),
script_chan: self.script_chan.sender(),
layout_chan: self.layout_chan.clone(),
}
}
Expand Down
39 changes: 24 additions & 15 deletions components/script/script_thread.rs
Expand Up @@ -840,10 +840,9 @@ impl ScriptThread {

let result = self.profile_event(category, move || {
match msg {
FromConstellation(ConstellationControlMsg::ExitPipeline(id)) => {
if self.handle_exit_pipeline_msg(id) {
return Some(false)
}
FromConstellation(ConstellationControlMsg::ExitScriptThread) => {
self.handle_exit_script_thread_msg();
return Some(false);
},
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
Expand Down Expand Up @@ -990,11 +989,13 @@ impl ScriptThread {
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
ConstellationControlMsg::Reload(pipeline_id) =>
self.handle_reload(pipeline_id),
ConstellationControlMsg::ExitPipeline(pipeline_id) =>
self.handle_exit_pipeline_msg(pipeline_id),
msg @ ConstellationControlMsg::AttachLayout(..) |
msg @ ConstellationControlMsg::Viewport(..) |
msg @ ConstellationControlMsg::SetScrollState(..) |
msg @ ConstellationControlMsg::Resize(..) |
msg @ ConstellationControlMsg::ExitPipeline(..) =>
msg @ ConstellationControlMsg::ExitScriptThread =>
panic!("should have handled {:?} already", msg),
}
}
Expand Down Expand Up @@ -1487,10 +1488,9 @@ impl ScriptThread {
document.send_title_to_compositor();
}

/// Handles a request to exit the script thread and shut down layout.
/// Returns true if the script thread should shut down and false otherwise.
fn handle_exit_pipeline_msg(&self, id: PipelineId) -> bool {
debug!("Exiting pipeline {:?}.", id);
/// Handles a request to exit a pipeline and shut down layout.
fn handle_exit_pipeline_msg(&self, id: PipelineId) {
debug!("Exiting pipeline {}.", id);

self.closed_pipelines.borrow_mut().insert(id);

Expand All @@ -1507,7 +1507,7 @@ impl ScriptThread {
let (response_chan, response_port) = channel();
let chan = &load.layout_chan;
if chan.send(message::Msg::PrepareToExit(response_chan)).is_ok() {
debug!("shutting down layout for page {:?}", id);
debug!("shutting down layout for page {}", id);
response_port.recv().unwrap();
chan.send(message::Msg::ExitNow).ok();
}
Expand All @@ -1518,13 +1518,22 @@ impl ScriptThread {
let _ = self.constellation_chan.send(ConstellationMsg::PipelineExited(id));
}

let no_pending_loads = self.incomplete_loads.borrow().is_empty();
let no_remaining_contexts = self.documents.borrow().is_empty();
debug!("Exited pipeline {}.", id);
}

debug!("Exited pipeline {:?} ({}&{}).", id, no_pending_loads, no_remaining_contexts);
/// Handles a request to exit the script thread and shut down layout.
fn handle_exit_script_thread_msg(&self) {
debug!("Exiting script thread.");

let mut pipeline_ids = Vec::new();
pipeline_ids.extend(self.incomplete_loads.borrow().iter().next().map(|load| load.pipeline_id));
pipeline_ids.extend(self.documents.borrow().iter().next().map(|(pipeline_id, _)| pipeline_id));

for pipeline_id in pipeline_ids {
self.handle_exit_pipeline_msg(pipeline_id);
}

// Exit if no pending loads and no remaining contexts
no_pending_loads && no_remaining_contexts
debug!("Exited script thread.");
}

/// Handles when layout thread finishes all animation in one tick
Expand Down
3 changes: 3 additions & 0 deletions components/script_traits/lib.rs
Expand Up @@ -195,6 +195,8 @@ pub enum ConstellationControlMsg {
ResizeInactive(PipelineId, WindowSizeData),
/// Notifies the script that a pipeline should be closed.
ExitPipeline(PipelineId),
/// Notifies the script that the whole thread should be closed.
ExitScriptThread,
/// Sends a DOM event.
SendEvent(PipelineId, CompositorEvent),
/// Notifies script of the viewport.
Expand Down Expand Up @@ -259,6 +261,7 @@ impl fmt::Debug for ConstellationControlMsg {
Resize(..) => "Resize",
ResizeInactive(..) => "ResizeInactive",
ExitPipeline(..) => "ExitPipeline",
ExitScriptThread => "ExitScriptThread",
SendEvent(..) => "SendEvent",
Viewport(..) => "Viewport",
SetScrollState(..) => "SetScrollState",
Expand Down

0 comments on commit 0e7ffaf

Please sign in to comment.