mirror of
https://github.com/servo/servo.git
synced 2025-09-27 15:20:09 +01:00
FxHash is faster than FnvHash and SipHash for simple types up to at least 64 bytes. The cryptographic guarantees are not needed for any types changed here because they are simple ids. This changes the types in script and net crates. In a future PR we will change the remaining Fnv to be also Fx unless there is a reason to keep them as Fnv. Testing: Should not change functionality but unit test and wpt will find it. Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
104 lines
3.9 KiB
Rust
104 lines
3.9 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use crossbeam_channel::{Receiver, select};
|
|
use devtools_traits::DevtoolScriptControlMsg;
|
|
use rustc_hash::FxHashSet;
|
|
|
|
use crate::dom::bindings::conversions::DerivedFrom;
|
|
use crate::dom::bindings::reflector::DomObject;
|
|
use crate::dom::dedicatedworkerglobalscope::AutoWorkerReset;
|
|
use crate::dom::globalscope::GlobalScope;
|
|
use crate::dom::worker::TrustedWorkerAddress;
|
|
use crate::dom::workerglobalscope::WorkerGlobalScope;
|
|
use crate::realms::enter_realm;
|
|
use crate::script_runtime::CanGc;
|
|
use crate::task_queue::{QueuedTaskConversion, TaskQueue};
|
|
|
|
pub(crate) trait WorkerEventLoopMethods {
|
|
type WorkerMsg: QueuedTaskConversion + Send;
|
|
type ControlMsg;
|
|
type Event;
|
|
fn task_queue(&self) -> &TaskQueue<Self::WorkerMsg>;
|
|
fn handle_event(&self, event: Self::Event, can_gc: CanGc) -> bool;
|
|
fn handle_worker_post_event(
|
|
&self,
|
|
worker: &TrustedWorkerAddress,
|
|
) -> Option<AutoWorkerReset<'_>>;
|
|
fn from_control_msg(msg: Self::ControlMsg) -> Self::Event;
|
|
fn from_worker_msg(msg: Self::WorkerMsg) -> Self::Event;
|
|
fn from_devtools_msg(msg: DevtoolScriptControlMsg) -> Self::Event;
|
|
fn from_timer_msg() -> Self::Event;
|
|
fn control_receiver(&self) -> &Receiver<Self::ControlMsg>;
|
|
}
|
|
|
|
// https://html.spec.whatwg.org/multipage/#worker-event-loop
|
|
pub(crate) fn run_worker_event_loop<T, WorkerMsg, Event>(
|
|
worker_scope: &T,
|
|
worker: Option<&TrustedWorkerAddress>,
|
|
can_gc: CanGc,
|
|
) where
|
|
WorkerMsg: QueuedTaskConversion + Send,
|
|
T: WorkerEventLoopMethods<WorkerMsg = WorkerMsg, Event = Event>
|
|
+ DerivedFrom<WorkerGlobalScope>
|
|
+ DerivedFrom<GlobalScope>
|
|
+ DomObject,
|
|
{
|
|
let scope = worker_scope.upcast::<WorkerGlobalScope>();
|
|
let task_queue = worker_scope.task_queue();
|
|
|
|
let never = crossbeam_channel::never();
|
|
let devtools_receiver = scope.devtools_receiver().unwrap_or(&never);
|
|
|
|
let event = select! {
|
|
recv(worker_scope.control_receiver()) -> msg => T::from_control_msg(msg.unwrap()),
|
|
recv(task_queue.select()) -> msg => {
|
|
task_queue.take_tasks(msg.unwrap(), &FxHashSet::default());
|
|
T::from_worker_msg(task_queue.recv().unwrap())
|
|
},
|
|
recv(devtools_receiver) -> msg => T::from_devtools_msg(msg.unwrap()),
|
|
recv(scope.timer_scheduler().wait_channel()) -> _ => T::from_timer_msg(),
|
|
};
|
|
|
|
scope.timer_scheduler().dispatch_completed_timers();
|
|
|
|
let mut sequential = vec![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.take_tasks_and_recv(&FxHashSet::default()) {
|
|
Err(_) => match devtools_receiver.try_recv() {
|
|
Ok(message) => sequential.push(T::from_devtools_msg(message)),
|
|
Err(_) => break,
|
|
},
|
|
Ok(ev) => sequential.push(T::from_worker_msg(ev)),
|
|
}
|
|
}
|
|
|
|
// Step 3
|
|
for event in sequential {
|
|
let _realm = enter_realm(worker_scope);
|
|
if !worker_scope.handle_event(event, can_gc) {
|
|
// Shutdown
|
|
return;
|
|
}
|
|
// 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(can_gc);
|
|
}
|
|
worker_scope
|
|
.upcast::<GlobalScope>()
|
|
.perform_a_dom_garbage_collection_checkpoint();
|
|
}
|