mirror of
https://github.com/servo/servo.git
synced 2025-06-25 17:44:33 +01:00
Script thread lifetime is now managed by the constellation.
This commit is contained in:
parent
18b7b5da07
commit
9ac6e4d2ba
4 changed files with 59 additions and 22 deletions
|
@ -52,6 +52,7 @@ use std::iter::once;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
@ -359,6 +360,30 @@ enum ExitPipelineMode {
|
||||||
Force,
|
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>) -> ScriptChan {
|
||||||
|
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
|
/// A logger directed at the constellation from content processes
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FromScriptLogger {
|
pub struct FromScriptLogger {
|
||||||
|
@ -554,7 +579,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
parent_info: Option<(PipelineId, FrameType)>,
|
parent_info: Option<(PipelineId, FrameType)>,
|
||||||
old_pipeline_id: Option<PipelineId>,
|
old_pipeline_id: Option<PipelineId>,
|
||||||
initial_window_size: Option<TypedSize2D<f32, PagePx>>,
|
initial_window_size: Option<TypedSize2D<f32, PagePx>>,
|
||||||
script_channel: Option<IpcSender<ConstellationControlMsg>>,
|
script_channel: Option<Rc<ScriptChan>>,
|
||||||
load_data: LoadData,
|
load_data: LoadData,
|
||||||
is_private: bool) {
|
is_private: bool) {
|
||||||
if self.shutting_down { return; }
|
if self.shutting_down { return; }
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use compositing::CompositionPipeline;
|
use compositing::CompositionPipeline;
|
||||||
use compositing::CompositorProxy;
|
use compositing::CompositorProxy;
|
||||||
use compositing::compositor_thread::Msg as CompositorMsg;
|
use compositing::compositor_thread::Msg as CompositorMsg;
|
||||||
|
use constellation::ScriptChan;
|
||||||
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
|
use devtools_traits::{DevtoolsControlMsg, ScriptToDevtoolsControlMsg};
|
||||||
use euclid::scale_factor::ScaleFactor;
|
use euclid::scale_factor::ScaleFactor;
|
||||||
use euclid::size::TypedSize2D;
|
use euclid::size::TypedSize2D;
|
||||||
|
@ -30,6 +31,7 @@ use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::io::Error as IOError;
|
use std::io::Error as IOError;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use style_traits::{PagePx, ViewportPx};
|
use style_traits::{PagePx, ViewportPx};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -50,7 +52,7 @@ pub struct Pipeline {
|
||||||
/// The ID of the frame that contains this Pipeline.
|
/// The ID of the frame that contains this Pipeline.
|
||||||
pub frame_id: FrameId,
|
pub frame_id: FrameId,
|
||||||
pub parent_info: Option<(PipelineId, FrameType)>,
|
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.
|
/// A channel to layout, for performing reflows and shutdown.
|
||||||
pub layout_chan: IpcSender<LayoutControlMsg>,
|
pub layout_chan: IpcSender<LayoutControlMsg>,
|
||||||
/// A channel to the compositor.
|
/// A channel to the compositor.
|
||||||
|
@ -113,7 +115,7 @@ pub struct InitialPipelineState {
|
||||||
pub device_pixel_ratio: ScaleFactor<f32, ViewportPx, DevicePixel>,
|
pub device_pixel_ratio: ScaleFactor<f32, ViewportPx, DevicePixel>,
|
||||||
/// A channel to the script thread, if applicable. If this is `Some`,
|
/// A channel to the script thread, if applicable. If this is `Some`,
|
||||||
/// then `parent_info` must also be `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.
|
/// Information about the page to load.
|
||||||
pub load_data: LoadData,
|
pub load_data: LoadData,
|
||||||
/// The ID of the pipeline namespace for this script thread.
|
/// The ID of the pipeline namespace for this script thread.
|
||||||
|
@ -165,7 +167,7 @@ impl Pipeline {
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let (script_chan, script_port) = ipc::channel().expect("Pipeline script chan");
|
let (script_chan, script_port) = ipc::channel().expect("Pipeline script chan");
|
||||||
(script_chan, Some((script_port, pipeline_port)))
|
(Rc::new(ScriptChan::new(script_chan)), Some((script_port, pipeline_port)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,7 +217,7 @@ impl Pipeline {
|
||||||
mem_profiler_chan: state.mem_profiler_chan,
|
mem_profiler_chan: state.mem_profiler_chan,
|
||||||
window_size: window_size,
|
window_size: window_size,
|
||||||
layout_to_constellation_chan: state.layout_to_constellation_chan,
|
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(),
|
load_data: state.load_data.clone(),
|
||||||
script_port: script_port,
|
script_port: script_port,
|
||||||
opts: (*opts::get()).clone(),
|
opts: (*opts::get()).clone(),
|
||||||
|
@ -258,7 +260,7 @@ impl Pipeline {
|
||||||
fn new(id: PipelineId,
|
fn new(id: PipelineId,
|
||||||
frame_id: FrameId,
|
frame_id: FrameId,
|
||||||
parent_info: Option<(PipelineId, FrameType)>,
|
parent_info: Option<(PipelineId, FrameType)>,
|
||||||
script_chan: IpcSender<ConstellationControlMsg>,
|
script_chan: Rc<ScriptChan>,
|
||||||
layout_chan: IpcSender<LayoutControlMsg>,
|
layout_chan: IpcSender<LayoutControlMsg>,
|
||||||
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
compositor_proxy: Box<CompositorProxy + 'static + Send>,
|
||||||
is_private: bool,
|
is_private: bool,
|
||||||
|
@ -329,7 +331,7 @@ impl Pipeline {
|
||||||
pub fn to_sendable(&self) -> CompositionPipeline {
|
pub fn to_sendable(&self) -> CompositionPipeline {
|
||||||
CompositionPipeline {
|
CompositionPipeline {
|
||||||
id: self.id.clone(),
|
id: self.id.clone(),
|
||||||
script_chan: self.script_chan.clone(),
|
script_chan: self.script_chan.sender(),
|
||||||
layout_chan: self.layout_chan.clone(),
|
layout_chan: self.layout_chan.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -842,10 +842,9 @@ impl ScriptThread {
|
||||||
|
|
||||||
let result = self.profile_event(category, move || {
|
let result = self.profile_event(category, move || {
|
||||||
match msg {
|
match msg {
|
||||||
FromConstellation(ConstellationControlMsg::ExitPipeline(id)) => {
|
FromConstellation(ConstellationControlMsg::ExitScriptThread) => {
|
||||||
if self.handle_exit_pipeline_msg(id) {
|
self.handle_exit_script_thread_msg();
|
||||||
return Some(false)
|
return Some(false);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
|
FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
|
||||||
FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
|
FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
|
||||||
|
@ -991,11 +990,13 @@ impl ScriptThread {
|
||||||
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
|
||||||
ConstellationControlMsg::Reload(pipeline_id) =>
|
ConstellationControlMsg::Reload(pipeline_id) =>
|
||||||
self.handle_reload(pipeline_id),
|
self.handle_reload(pipeline_id),
|
||||||
|
ConstellationControlMsg::ExitPipeline(pipeline_id) =>
|
||||||
|
self.handle_exit_pipeline_msg(pipeline_id),
|
||||||
msg @ ConstellationControlMsg::AttachLayout(..) |
|
msg @ ConstellationControlMsg::AttachLayout(..) |
|
||||||
msg @ ConstellationControlMsg::Viewport(..) |
|
msg @ ConstellationControlMsg::Viewport(..) |
|
||||||
msg @ ConstellationControlMsg::SetScrollState(..) |
|
msg @ ConstellationControlMsg::SetScrollState(..) |
|
||||||
msg @ ConstellationControlMsg::Resize(..) |
|
msg @ ConstellationControlMsg::Resize(..) |
|
||||||
msg @ ConstellationControlMsg::ExitPipeline(..) =>
|
msg @ ConstellationControlMsg::ExitScriptThread =>
|
||||||
panic!("should have handled {:?} already", msg),
|
panic!("should have handled {:?} already", msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1486,10 +1487,9 @@ impl ScriptThread {
|
||||||
document.send_title_to_compositor();
|
document.send_title_to_compositor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a request to exit the script thread and shut down layout.
|
/// Handles a request to exit a pipeline and shut down layout.
|
||||||
/// Returns true if the script thread should shut down and false otherwise.
|
fn handle_exit_pipeline_msg(&self, id: PipelineId) {
|
||||||
fn handle_exit_pipeline_msg(&self, id: PipelineId) -> bool {
|
debug!("Exiting pipeline {}.", id);
|
||||||
debug!("Exiting pipeline {:?}.", id);
|
|
||||||
|
|
||||||
self.closed_pipelines.borrow_mut().insert(id);
|
self.closed_pipelines.borrow_mut().insert(id);
|
||||||
|
|
||||||
|
@ -1506,7 +1506,7 @@ impl ScriptThread {
|
||||||
let (response_chan, response_port) = channel();
|
let (response_chan, response_port) = channel();
|
||||||
let chan = &load.layout_chan;
|
let chan = &load.layout_chan;
|
||||||
if chan.send(message::Msg::PrepareToExit(response_chan)).is_ok() {
|
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();
|
response_port.recv().unwrap();
|
||||||
chan.send(message::Msg::ExitNow).ok();
|
chan.send(message::Msg::ExitNow).ok();
|
||||||
}
|
}
|
||||||
|
@ -1517,13 +1517,20 @@ impl ScriptThread {
|
||||||
let _ = self.constellation_chan.send(ConstellationMsg::PipelineExited(id));
|
let _ = self.constellation_chan.send(ConstellationMsg::PipelineExited(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let no_pending_loads = self.incomplete_loads.borrow().is_empty();
|
debug!("Exited pipeline {}.", id);
|
||||||
let no_remaining_contexts = self.documents.borrow().is_empty();
|
}
|
||||||
|
|
||||||
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.");
|
||||||
|
|
||||||
// Exit if no pending loads and no remaining contexts
|
while let Some(pipeline_id) = self.incomplete_loads.borrow().iter().next().map(|load| load.pipeline_id)
|
||||||
no_pending_loads && no_remaining_contexts
|
.or_else(|| self.documents.borrow().iter().next().map(|doc| doc.global().pipeline_id()))
|
||||||
|
{
|
||||||
|
self.handle_exit_pipeline_msg(pipeline_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Exited script thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles when layout thread finishes all animation in one tick
|
/// Handles when layout thread finishes all animation in one tick
|
||||||
|
|
|
@ -193,6 +193,8 @@ pub enum ConstellationControlMsg {
|
||||||
ResizeInactive(PipelineId, WindowSizeData),
|
ResizeInactive(PipelineId, WindowSizeData),
|
||||||
/// Notifies the script that a pipeline should be closed.
|
/// Notifies the script that a pipeline should be closed.
|
||||||
ExitPipeline(PipelineId),
|
ExitPipeline(PipelineId),
|
||||||
|
/// Notifies the script that the whole thread should be closed.
|
||||||
|
ExitScriptThread,
|
||||||
/// Sends a DOM event.
|
/// Sends a DOM event.
|
||||||
SendEvent(PipelineId, CompositorEvent),
|
SendEvent(PipelineId, CompositorEvent),
|
||||||
/// Notifies script of the viewport.
|
/// Notifies script of the viewport.
|
||||||
|
@ -257,6 +259,7 @@ impl fmt::Debug for ConstellationControlMsg {
|
||||||
Resize(..) => "Resize",
|
Resize(..) => "Resize",
|
||||||
ResizeInactive(..) => "ResizeInactive",
|
ResizeInactive(..) => "ResizeInactive",
|
||||||
ExitPipeline(..) => "ExitPipeline",
|
ExitPipeline(..) => "ExitPipeline",
|
||||||
|
ExitScriptThread => "ExitScriptThread",
|
||||||
SendEvent(..) => "SendEvent",
|
SendEvent(..) => "SendEvent",
|
||||||
Viewport(..) => "Viewport",
|
Viewport(..) => "Viewport",
|
||||||
SetScrollState(..) => "SetScrollState",
|
SetScrollState(..) => "SetScrollState",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue