diff options
author | Gregory Terzian <gterzian@users.noreply.github.com> | 2018-08-18 20:28:42 +0200 |
---|---|---|
committer | Gregory Terzian <gterzian@users.noreply.github.com> | 2018-08-31 02:10:45 +0800 |
commit | 029715aba6f4a4c62b5a2759d47dda57954cc433 (patch) | |
tree | ed529c6a3c958f04b489882818884e10b0d3a11d /components/script/dom/abstractworkerglobalscope.rs | |
parent | ca6306c4306b0d13a7e886f4308ee703fcb1b2b3 (diff) | |
download | servo-029715aba6f4a4c62b5a2759d47dda57954cc433.tar.gz servo-029715aba6f4a4c62b5a2759d47dda57954cc433.zip |
introduce a generic worker event-loop
Diffstat (limited to 'components/script/dom/abstractworkerglobalscope.rs')
-rw-r--r-- | components/script/dom/abstractworkerglobalscope.rs | 94 |
1 files changed, 92 insertions, 2 deletions
diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs index 99c08dc2c38..45c594dbaee 100644 --- a/components/script/dom/abstractworkerglobalscope.rs +++ b/components/script/dom/abstractworkerglobalscope.rs @@ -2,11 +2,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use devtools_traits::DevtoolScriptControlMsg; use dom::abstractworker::WorkerScriptMsg; -use dom::dedicatedworkerglobalscope::DedicatedWorkerScriptMsg; +use dom::bindings::conversions::DerivedFrom; +use dom::bindings::reflector::DomObject; +use dom::dedicatedworkerglobalscope::{AutoWorkerReset, DedicatedWorkerScriptMsg}; +use dom::globalscope::GlobalScope; use dom::worker::TrustedWorkerAddress; +use dom::workerglobalscope::WorkerGlobalScope; use script_runtime::{ScriptChan, CommonScriptMsg, ScriptPort}; -use std::sync::mpsc::{Receiver, Sender}; +use std::sync::mpsc::{Receiver, Select, Sender}; +use task_queue::{QueuedTaskConversion, TaskQueue}; /// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with /// common event loop messages. While this SendableWorkerScriptChan is alive, the associated @@ -69,3 +75,87 @@ impl ScriptPort for Receiver<DedicatedWorkerScriptMsg> { } } } + +pub trait WorkerEventLoopMethods { + type TimerMsg: Send; + type WorkerMsg: QueuedTaskConversion + Send; + type Event; + fn timer_event_port(&self) -> &Receiver<Self::TimerMsg>; + fn task_queue(&self) -> &TaskQueue<Self::WorkerMsg>; + fn handle_event(&self, event: Self::Event); + fn handle_worker_post_event(&self, worker: &TrustedWorkerAddress) -> Option<AutoWorkerReset>; + fn from_worker_msg(&self, msg: Self::WorkerMsg) -> Self::Event; + fn from_timer_msg(&self, msg: Self::TimerMsg) -> Self::Event; + fn from_devtools_msg(&self, msg: DevtoolScriptControlMsg) -> Self::Event; +} + +#[allow(unsafe_code)] +// https://html.spec.whatwg.org/multipage/#worker-event-loop +pub fn run_worker_event_loop<T, TimerMsg, WorkerMsg, Event>(worker_scope: &T, + worker: Option<&TrustedWorkerAddress>) +where + TimerMsg: Send, + WorkerMsg: QueuedTaskConversion + Send, + T: WorkerEventLoopMethods<TimerMsg = TimerMsg, WorkerMsg = WorkerMsg, Event = Event> + + DerivedFrom<WorkerGlobalScope> + DerivedFrom<GlobalScope> + + DomObject { + let scope = worker_scope.upcast::<WorkerGlobalScope>(); + let timer_event_port = worker_scope.timer_event_port(); + let devtools_port = scope.from_devtools_receiver(); + let task_queue = worker_scope.task_queue(); + let sel = Select::new(); + let mut worker_handle = sel.handle(task_queue.select()); + let mut timer_event_handle = sel.handle(timer_event_port); + let mut devtools_handle = sel.handle(devtools_port); + unsafe { + worker_handle.add(); + timer_event_handle.add(); + if scope.from_devtools_sender().is_some() { + devtools_handle.add(); + } + } + let ret = sel.wait(); + let event = { + if ret == worker_handle.id() { + task_queue.take_tasks(); + worker_scope.from_worker_msg(task_queue.recv().unwrap()) + } else if ret == timer_event_handle.id() { + worker_scope.from_timer_msg(timer_event_port.recv().unwrap()) + } else if ret == devtools_handle.id() { + worker_scope.from_devtools_msg(devtools_port.recv().unwrap()) + } else { + panic!("unexpected select result!") + } + }; + let mut sequential = vec![]; + sequential.push(event); + // https://html.spec.whatwg.org/multipage/#worker-event-loop + // Once the WorkerGlobalScope's closing flag is set to true, + // the event loop's task queues must discard any further tasks + // that would be added to them + // (tasks already on the queue are unaffected except where otherwise specified). + while !scope.is_closing() { + // Batch all events that are ready. + // The task queue will throttle non-priority tasks if necessary. + match task_queue.try_recv() { + Err(_) => match timer_event_port.try_recv() { + Err(_) => match devtools_port.try_recv() { + Err(_) => break, + Ok(ev) => sequential.push(worker_scope.from_devtools_msg(ev)), + }, + Ok(ev) => sequential.push(worker_scope.from_timer_msg(ev)), + }, + Ok(ev) => sequential.push(worker_scope.from_worker_msg(ev)), + } + } + // Step 3 + for event in sequential { + worker_scope.handle_event(event); + // Step 6 + let _ar = match worker { + Some(worker) => worker_scope.handle_worker_post_event(worker), + None => None + }; + worker_scope.upcast::<GlobalScope>().perform_a_microtask_checkpoint(); + } +} |