aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
authorbenshu <benshu@benshu.de>2015-08-30 01:45:07 +0200
committerbenshu <benshu@benshu.de>2015-10-21 16:40:49 +0200
commit553a0dbefd8a8724f7c894b1c25e6c15c35d6d04 (patch)
tree8f49ff753b6f91397865a26f4bd8c14a12377e96 /components/script/script_task.rs
parent674589c370d978f543e71f995d58c5b28e6e9842 (diff)
downloadservo-553a0dbefd8a8724f7c894b1c25e6c15c35d6d04.tar.gz
servo-553a0dbefd8a8724f7c894b1c25e6c15c35d6d04.zip
Timers are scheduled by a dedicated per-constellation thread.
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs117
1 files changed, 73 insertions, 44 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index 79e749b82d6..a090d1c91ef 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -82,6 +82,7 @@ use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent};
use script_traits::{CompositorEvent, ConstellationControlMsg};
use script_traits::{InitialScriptState, MouseButton, NewLayoutInfo};
use script_traits::{OpaqueScriptLayoutChannel, ScriptState, ScriptTaskFactory};
+use script_traits::{TimerEvent, TimerEventChan, TimerEventRequest, TimerSource};
use std::any::Any;
use std::borrow::ToOwned;
use std::cell::{Cell, RefCell};
@@ -96,7 +97,6 @@ use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::sync::{Arc, Mutex};
use string_cache::Atom;
use time::{Tm, now};
-use timers::TimerId;
use url::{Url, UrlParser};
use util::opts;
use util::str::DOMString;
@@ -156,12 +156,6 @@ impl InProgressLoad {
}
}
-#[derive(Copy, Clone)]
-pub enum TimerSource {
- FromWindow(PipelineId),
- FromWorker
-}
-
pub trait Runnable {
fn handler(self: Box<Self>);
}
@@ -175,6 +169,7 @@ enum MixedMessage {
FromScript(MainThreadScriptMsg),
FromDevtools(DevtoolScriptControlMsg),
FromImageCache(ImageCacheResult),
+ FromScheduler(TimerEvent),
}
/// Common messages used to control the event loops in both the script and the worker
@@ -182,10 +177,6 @@ pub enum CommonScriptMsg {
/// Requests that the script task measure its memory usage. The results are sent back via the
/// supplied channel.
CollectReports(ReportsChan),
- /// Fires a JavaScript timeout
- /// TimerSource must be FromWindow when dispatched to ScriptTask and
- /// must be FromWorker when dispatched to a DedicatedGlobalWorkerScope
- FireTimer(TimerSource, TimerId),
/// A DOM object's last pinned reference was removed (dispatched to all tasks).
RefcountCleanup(TrustedReference),
/// Generic message that encapsulates event handling.
@@ -205,6 +196,7 @@ pub enum ScriptTaskEventCategory {
NetworkEvent,
Resize,
ScriptEvent,
+ TimerEvent,
UpdateReplacedElement,
SetViewport,
WebSocketEvent,
@@ -327,6 +319,20 @@ impl MainThreadScriptChan {
}
}
+pub struct MainThreadTimerEventChan(Sender<TimerEvent>);
+
+impl TimerEventChan for MainThreadTimerEventChan {
+ fn send(&self, event: TimerEvent) -> Result<(), ()> {
+ let MainThreadTimerEventChan(ref chan) = *self;
+ chan.send(event).map_err(|_| ())
+ }
+
+ fn clone(&self) -> Box<TimerEventChan + Send> {
+ let MainThreadTimerEventChan(ref chan) = *self;
+ box MainThreadTimerEventChan((*chan).clone())
+ }
+}
+
pub struct StackRootTLS;
impl StackRootTLS {
@@ -408,6 +414,10 @@ pub struct ScriptTask {
/// List of pipelines that have been owned and closed by this script task.
closed_pipelines: RefCell<HashSet<PipelineId>>,
+
+ scheduler_chan: Sender<TimerEventRequest>,
+ timer_event_chan: Sender<TimerEvent>,
+ timer_event_port: Receiver<TimerEvent>,
}
/// In the event of task failure, all data on the stack runs its destructor. However, there
@@ -604,6 +614,8 @@ impl ScriptTask {
let image_cache_port =
ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_image_cache_port);
+ let (timer_event_chan, timer_event_port) = channel();
+
ScriptTask {
page: DOMRefCell::new(None),
incomplete_loads: DOMRefCell::new(vec!()),
@@ -631,6 +643,10 @@ impl ScriptTask {
js_runtime: Rc::new(runtime),
mouse_over_targets: DOMRefCell::new(vec!()),
closed_pipelines: RefCell::new(HashSet::new()),
+
+ scheduler_chan: state.scheduler_chan,
+ timer_event_chan: timer_event_chan,
+ timer_event_port: timer_event_port,
}
}
@@ -717,26 +733,30 @@ impl ScriptTask {
// Receive at least one message so we don't spinloop.
let mut event = {
let sel = Select::new();
- let mut port1 = sel.handle(&self.port);
- let mut port2 = sel.handle(&self.control_port);
- let mut port3 = sel.handle(&self.devtools_port);
- let mut port4 = sel.handle(&self.image_cache_port);
+ let mut script_port = sel.handle(&self.port);
+ let mut control_port = sel.handle(&self.control_port);
+ let mut timer_event_port = sel.handle(&self.timer_event_port);
+ let mut devtools_port = sel.handle(&self.devtools_port);
+ let mut image_cache_port = sel.handle(&self.image_cache_port);
unsafe {
- port1.add();
- port2.add();
+ script_port.add();
+ control_port.add();
+ timer_event_port.add();
if self.devtools_chan.is_some() {
- port3.add();
+ devtools_port.add();
}
- port4.add();
+ image_cache_port.add();
}
let ret = sel.wait();
- if ret == port1.id() {
+ if ret == script_port.id() {
MixedMessage::FromScript(self.port.recv().unwrap())
- } else if ret == port2.id() {
+ } else if ret == control_port.id() {
MixedMessage::FromConstellation(self.control_port.recv().unwrap())
- } else if ret == port3.id() {
+ } else if ret == timer_event_port.id() {
+ MixedMessage::FromScheduler(self.timer_event_port.recv().unwrap())
+ } else if ret == devtools_port.id() {
MixedMessage::FromDevtools(self.devtools_port.recv().unwrap())
- } else if ret == port4.id() {
+ } else if ret == image_cache_port.id() {
MixedMessage::FromImageCache(self.image_cache_port.recv().unwrap())
} else {
panic!("unexpected select result")
@@ -797,12 +817,15 @@ impl ScriptTask {
// on and execute the sequential non-resize events we've seen.
match self.control_port.try_recv() {
Err(_) => match self.port.try_recv() {
- Err(_) => match self.devtools_port.try_recv() {
- Err(_) => match self.image_cache_port.try_recv() {
- Err(_) => break,
- Ok(ev) => event = MixedMessage::FromImageCache(ev),
+ Err(_) => match self.timer_event_port.try_recv() {
+ Err(_) => match self.devtools_port.try_recv() {
+ Err(_) => match self.image_cache_port.try_recv() {
+ Err(_) => break,
+ Ok(ev) => event = MixedMessage::FromImageCache(ev),
+ },
+ Ok(ev) => event = MixedMessage::FromDevtools(ev),
},
- Ok(ev) => event = MixedMessage::FromDevtools(ev),
+ Ok(ev) => event = MixedMessage::FromScheduler(ev),
},
Ok(ev) => event = MixedMessage::FromScript(ev),
},
@@ -823,6 +846,7 @@ impl ScriptTask {
},
MixedMessage::FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
MixedMessage::FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
+ MixedMessage::FromScheduler(inner_msg) => self.handle_timer_event(inner_msg),
MixedMessage::FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
MixedMessage::FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
}
@@ -871,7 +895,8 @@ impl ScriptTask {
*category,
_ => ScriptTaskEventCategory::ScriptEvent
}
- }
+ },
+ MixedMessage::FromScheduler(_) => ScriptTaskEventCategory::TimerEvent,
}
}
@@ -893,6 +918,7 @@ impl ScriptTask {
ScriptTaskEventCategory::ScriptEvent => ProfilerCategory::ScriptEvent,
ScriptTaskEventCategory::UpdateReplacedElement => ProfilerCategory::ScriptUpdateReplacedElement,
ScriptTaskEventCategory::SetViewport => ProfilerCategory::ScriptSetViewport,
+ ScriptTaskEventCategory::TimerEvent => ProfilerCategory::ScriptTimerEvent,
ScriptTaskEventCategory::WebSocketEvent => ProfilerCategory::ScriptWebSocketEvent,
ScriptTaskEventCategory::WorkerEvent => ProfilerCategory::ScriptWorkerEvent,
ScriptTaskEventCategory::XhrEvent => ProfilerCategory::ScriptXhrEvent,
@@ -966,12 +992,6 @@ impl ScriptTask {
runnable.handler(self),
MainThreadScriptMsg::DocumentLoadsComplete(id) =>
self.handle_loads_complete(id),
- MainThreadScriptMsg::Common(
- CommonScriptMsg::FireTimer(TimerSource::FromWindow(id), timer_id)) =>
- self.handle_fire_timer_msg(id, timer_id),
- MainThreadScriptMsg::Common(
- CommonScriptMsg::FireTimer(TimerSource::FromWorker, _)) =>
- panic!("Worker timeouts must not be sent to script task"),
MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) =>
// The category of the runnable is ignored by the pattern, however
// it is still respected by profiling (see categorize_msg).
@@ -983,6 +1003,22 @@ impl ScriptTask {
}
}
+ fn handle_timer_event(&self, timer_event: TimerEvent) {
+ let TimerEvent(source, id) = timer_event;
+
+ let pipeline_id = match source {
+ TimerSource::FromWindow(pipeline_id) => pipeline_id,
+ TimerSource::FromWorker => panic!("Worker timeouts must not be sent to script task"),
+ };
+
+ let page = self.root_page();
+ let page = page.find(pipeline_id).expect("ScriptTask: received fire timer msg for a
+ pipeline ID not associated with this script task. This is a bug.");
+ let window = page.window();
+
+ window.r().handle_fire_timer(id);
+ }
+
fn handle_msg_from_devtools(&self, msg: DevtoolScriptControlMsg) {
let page = self.root_page();
match msg {
@@ -1272,15 +1308,6 @@ impl ScriptTask {
reports_chan.send(reports);
}
- /// Handles a timer that fired.
- fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
- let page = self.root_page();
- let page = page.find(id).expect("ScriptTask: received fire timer msg for a
- pipeline ID not associated with this script task. This is a bug.");
- let window = page.window();
- window.r().handle_fire_timer(timer_id);
- }
-
/// Handles freeze message
fn handle_freeze_msg(&self, id: PipelineId) {
// Workaround for a race condition when navigating before the initial page has
@@ -1587,6 +1614,8 @@ impl ScriptTask {
self.mem_profiler_chan.clone(),
self.devtools_chan.clone(),
self.constellation_chan.clone(),
+ self.scheduler_chan.clone(),
+ MainThreadTimerEventChan(self.timer_event_chan.clone()),
incomplete.layout_chan,
incomplete.pipeline_id,
incomplete.parent_info,