aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_thread.rs
diff options
context:
space:
mode:
authorGregory Terzian <gterzian@users.noreply.github.com>2018-08-11 00:08:00 +0200
committerGregory Terzian <gterzian@users.noreply.github.com>2018-08-31 02:10:34 +0800
commitca6306c4306b0d13a7e886f4308ee703fcb1b2b3 (patch)
treea27c1a4dcbcaebd9a182de5efb1c1f1b5fa5e862 /components/script/script_thread.rs
parentda36740f0b1a48f5a4b4ed86318e110f1e63554b (diff)
downloadservo-ca6306c4306b0d13a7e886f4308ee703fcb1b2b3.tar.gz
servo-ca6306c4306b0d13a7e886f4308ee703fcb1b2b3.zip
introduce task-queues, and throttling the performance-timeline task-source, in script and worker threads.
queue
Diffstat (limited to 'components/script/script_thread.rs')
-rw-r--r--components/script/script_thread.rs67
1 files changed, 61 insertions, 6 deletions
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 011a3f0106f..e6de4a60fbc 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -116,6 +116,7 @@ use std::sync::Arc;
use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::thread;
use style::thread_state::{self, ThreadState};
+use task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
use task_source::dom_manipulation::DOMManipulationTaskSource;
use task_source::file_reading::FileReadingTaskSource;
use task_source::history_traversal::HistoryTraversalTaskSource;
@@ -242,6 +243,52 @@ pub enum MainThreadScriptMsg {
},
/// Dispatches a job queue.
DispatchJobQueue { scope_url: ServoUrl },
+ /// Wake-up call from the task queue.
+ WakeUp,
+}
+
+impl QueuedTaskConversion for MainThreadScriptMsg {
+ fn task_category(&self) -> Option<&ScriptThreadEventCategory> {
+ let script_msg = match self {
+ MainThreadScriptMsg::Common(script_msg) => script_msg,
+ _ => return None,
+ };
+ let category = match script_msg {
+ CommonScriptMsg::Task(category, _boxed, _pipeline_id) => category,
+ _ => return None,
+ };
+ Some(&category)
+ }
+
+ fn into_queued_task(self) -> Option<QueuedTask> {
+ let script_msg = match self {
+ MainThreadScriptMsg::Common(script_msg) => script_msg,
+ _ => return None,
+ };
+ let (category, boxed, pipeline_id) = match script_msg {
+ CommonScriptMsg::Task(category, boxed, pipeline_id) =>
+ (category, boxed, pipeline_id),
+ _ => return None,
+ };
+ Some((None, category, boxed, pipeline_id))
+ }
+
+ fn from_queued_task(queued_task: QueuedTask) -> Self {
+ let (_worker, category, boxed, pipeline_id) = queued_task;
+ let script_msg = CommonScriptMsg::Task(category, boxed, pipeline_id);
+ MainThreadScriptMsg::Common(script_msg)
+ }
+
+ fn wake_up_msg() -> Self {
+ MainThreadScriptMsg::WakeUp
+ }
+
+ fn is_wake_up(&self) -> bool {
+ match self {
+ MainThreadScriptMsg::WakeUp => true,
+ _ => false,
+ }
+ }
}
impl OpaqueSender<CommonScriptMsg> for Box<ScriptChan + Send> {
@@ -398,6 +445,8 @@ impl<'a> Iterator for DocumentsIter<'a> {
type IncompleteParserContexts = Vec<(PipelineId, ParserContext)>;
unsafe_no_jsmanaged_fields!(RefCell<IncompleteParserContexts>);
+unsafe_no_jsmanaged_fields!(TaskQueue<MainThreadScriptMsg>);
+
#[derive(JSTraceable)]
// ScriptThread instances are rooted on creation, so this is okay
#[allow(unrooted_must_root)]
@@ -423,8 +472,9 @@ pub struct ScriptThread {
/// A handle to the bluetooth thread.
bluetooth_thread: IpcSender<BluetoothRequest>,
- /// The port on which the script thread receives messages (load URL, exit, etc.)
- port: Receiver<MainThreadScriptMsg>,
+ /// A queue of tasks to be executed in this script-thread.
+ task_queue: TaskQueue<MainThreadScriptMsg>,
+
/// A channel to hand out to script thread-based entities that need to be able to enqueue
/// events in the event queue.
chan: MainThreadScriptChan,
@@ -856,6 +906,8 @@ impl ScriptThread {
let (image_cache_channel, image_cache_port) = channel();
+ let task_queue = TaskQueue::new(port, chan.clone());
+
ScriptThread {
documents: DomRefCell::new(Documents::new()),
window_proxies: DomRefCell::new(HashMap::new()),
@@ -871,7 +923,7 @@ impl ScriptThread {
resource_threads: state.resource_threads,
bluetooth_thread: state.bluetooth_thread,
- port: port,
+ task_queue,
chan: MainThreadScriptChan(chan.clone()),
dom_manipulation_task_sender: chan.clone(),
@@ -968,7 +1020,7 @@ impl ScriptThread {
debug!("Waiting for event.");
let mut event = {
let sel = Select::new();
- let mut script_port = sel.handle(&self.port);
+ let mut script_port = sel.handle(self.task_queue.select());
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);
@@ -984,7 +1036,8 @@ impl ScriptThread {
}
let ret = sel.wait();
if ret == script_port.id() {
- FromScript(self.port.recv().unwrap())
+ self.task_queue.take_tasks();
+ FromScript(self.task_queue.recv().unwrap())
} else if ret == control_port.id() {
FromConstellation(self.control_port.recv().unwrap())
} else if ret == timer_event_port.id() {
@@ -1077,7 +1130,7 @@ impl ScriptThread {
// and check for more resize events. If there are no events pending, we'll move
// 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.task_queue.try_recv() {
Err(_) => match self.timer_event_port.try_recv() {
Err(_) => match self.devtools_port.try_recv() {
Err(_) => match self.image_cache_port.try_recv() {
@@ -1233,6 +1286,7 @@ impl ScriptThread {
MainThreadScriptMsg::WorkletLoaded(pipeline_id) => Some(pipeline_id),
MainThreadScriptMsg::RegisterPaintWorklet { pipeline_id, .. } => Some(pipeline_id),
MainThreadScriptMsg::DispatchJobQueue { .. } => None,
+ MainThreadScriptMsg::WakeUp => None,
}
},
MixedMessage::FromImageCache((pipeline_id, _)) => Some(pipeline_id),
@@ -1404,6 +1458,7 @@ impl ScriptThread {
MainThreadScriptMsg::DispatchJobQueue { scope_url } => {
self.job_queue_map.run_job(scope_url, self)
}
+ MainThreadScriptMsg::WakeUp => {},
}
}