Introduce TaskOnce

Having both TaskBox and TaskOnce allows us to remove the superfluous inner boxing
from CancellableTask<T>.
This commit is contained in:
Anthony Ramine 2017-09-20 10:37:09 +02:00
parent 52527d6f9d
commit 6c9fb5ae7a
26 changed files with 144 additions and 124 deletions

View file

@ -40,7 +40,7 @@ use std::marker::PhantomData;
use std::os; use std::os;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use task::TaskBox; use task::TaskOnce;
#[allow(missing_docs)] // FIXME #[allow(missing_docs)] // FIXME
@ -122,7 +122,7 @@ impl TrustedPromise {
/// A task which will reject the promise. /// A task which will reject the promise.
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn reject_task(self, error: Error) -> impl TaskBox { pub fn reject_task(self, error: Error) -> impl TaskOnce {
let this = self; let this = self;
task!(reject_promise: move || { task!(reject_promise: move || {
debug!("Rejecting promise."); debug!("Rejecting promise.");
@ -135,7 +135,7 @@ impl TrustedPromise {
/// A task which will resolve the promise. /// A task which will resolve the promise.
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn resolve_task<T>(self, value: T) -> impl TaskBox pub fn resolve_task<T>(self, value: T) -> impl TaskOnce
where where
T: ToJSValConvertible + Send, T: ToJSValConvertible + Send,
{ {

View file

@ -40,7 +40,7 @@ use std::collections::HashMap;
use std::rc::Rc; use std::rc::Rc;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use task::TaskBox; use task::TaskOnce;
const KEY_CONVERSION_ERROR: &'static str = "This `manufacturerData` key can not be parsed as unsigned short:"; const KEY_CONVERSION_ERROR: &'static str = "This `manufacturerData` key can not be parsed as unsigned short:";
const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices."; const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices.";
@ -229,18 +229,17 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>(
action: BluetoothResponseResult, action: BluetoothResponseResult,
} }
impl<T> TaskBox for ListenerTask<T> impl<T> TaskOnce for ListenerTask<T>
where where
T: AsyncBluetoothListener + DomObject, T: AsyncBluetoothListener + DomObject,
{ {
fn run_box(self: Box<Self>) { fn run_once(self) {
let this = *self; let mut context = self.context.lock().unwrap();
let mut context = this.context.lock().unwrap(); context.response(self.action);
context.response(this.action);
} }
} }
let task = box ListenerTask { let task = ListenerTask {
context: context.clone(), context: context.clone(),
action: message.to().unwrap(), action: message.to().unwrap(),
}; };

View file

@ -1716,7 +1716,7 @@ impl Document {
debug!("Document loads are complete."); debug!("Document loads are complete.");
let document = Trusted::new(self); let document = Trusted::new(self);
self.window.dom_manipulation_task_source().queue( self.window.dom_manipulation_task_source().queue(
box task!(fire_load_event: move || { task!(fire_load_event: move || {
let document = document.root(); let document = document.root();
let window = document.window(); let window = document.window();
if !window.is_alive() { if !window.is_alive() {

View file

@ -119,7 +119,7 @@ use style::thread_state;
use style::values::{CSSFloat, Either}; use style::values::{CSSFloat, Either};
use style::values::{specified, computed}; use style::values::{specified, computed};
use stylesheet_loader::StylesheetOwner; use stylesheet_loader::StylesheetOwner;
use task::TaskBox; use task::TaskOnce;
// TODO: Update focus state when the top-level browsing context gains or loses system focus, // TODO: Update focus state when the top-level browsing context gains or loses system focus,
// and when the element enters or leaves a browsing context container. // and when the element enters or leaves a browsing context container.
@ -3047,9 +3047,9 @@ impl ElementPerformFullscreenEnter {
} }
} }
impl TaskBox for ElementPerformFullscreenEnter { impl TaskOnce for ElementPerformFullscreenEnter {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn run_box(self: Box<Self>) { fn run_once(self) {
let element = self.element.root(); let element = self.element.root();
let document = document_from_node(element.r()); let document = document_from_node(element.r());
@ -3100,9 +3100,9 @@ impl ElementPerformFullscreenExit {
} }
} }
impl TaskBox for ElementPerformFullscreenExit { impl TaskOnce for ElementPerformFullscreenExit {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn run_box(self: Box<Self>) { fn run_once(self) {
let element = self.element.root(); let element = self.element.root();
let document = document_from_node(element.r()); let document = document_from_node(element.r());
// TODO Step 9.1-5 // TODO Step 9.1-5

View file

@ -23,7 +23,7 @@ use dom_struct::dom_struct;
use servo_atoms::Atom; use servo_atoms::Atom;
use std::cell::Cell; use std::cell::Cell;
use std::default::Default; use std::default::Default;
use task::TaskBox; use task::TaskOnce;
use time; use time;
#[dom_struct] #[dom_struct]
@ -388,8 +388,8 @@ pub struct EventTask {
pub cancelable: EventCancelable, pub cancelable: EventCancelable,
} }
impl TaskBox for EventTask { impl TaskOnce for EventTask {
fn run_box(self: Box<Self>) { fn run_once(self) {
let target = self.target.root(); let target = self.target.root();
let bubbles = self.bubbles; let bubbles = self.bubbles;
let cancelable = self.cancelable; let cancelable = self.cancelable;
@ -403,8 +403,8 @@ pub struct SimpleEventTask {
pub name: Atom, pub name: Atom,
} }
impl TaskBox for SimpleEventTask { impl TaskOnce for SimpleEventTask {
fn run_box(self: Box<Self>) { fn run_once(self) {
let target = self.target.root(); let target = self.target.root();
target.fire_event(self.name); target.fire_event(self.name);
} }

View file

@ -100,7 +100,7 @@ impl EventSourceContext {
let event_source = self.event_source.clone(); let event_source = self.event_source.clone();
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = global.networking_task_source().queue( let _ = global.networking_task_source().queue(
box task!(announce_the_event_source_connection: move || { task!(announce_the_event_source_connection: move || {
let event_source = event_source.root(); let event_source = event_source.root();
if event_source.ready_state.get() != ReadyState::Closed { if event_source.ready_state.get() != ReadyState::Closed {
event_source.ready_state.set(ReadyState::Open); event_source.ready_state.set(ReadyState::Open);
@ -121,7 +121,7 @@ impl EventSourceContext {
let event_source = self.event_source.clone(); let event_source = self.event_source.clone();
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = global.networking_task_source().queue( let _ = global.networking_task_source().queue(
box task!(fail_the_event_source_connection: move || { task!(fail_the_event_source_connection: move || {
let event_source = event_source.root(); let event_source = event_source.root();
if event_source.ready_state.get() != ReadyState::Closed { if event_source.ready_state.get() != ReadyState::Closed {
event_source.ready_state.set(ReadyState::Closed); event_source.ready_state.set(ReadyState::Closed);
@ -145,7 +145,7 @@ impl EventSourceContext {
let global = event_source.global(); let global = event_source.global();
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = global.networking_task_source().queue( let _ = global.networking_task_source().queue(
box task!(reestablish_the_event_source_onnection: move || { task!(reestablish_the_event_source_onnection: move || {
let event_source = trusted_event_source.root(); let event_source = trusted_event_source.root();
// Step 1.1. // Step 1.1.
@ -242,7 +242,7 @@ impl EventSourceContext {
let event = Trusted::new(&*event); let event = Trusted::new(&*event);
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = global.networking_task_source().queue( let _ = global.networking_task_source().queue(
box task!(dispatch_the_event_source_event: move || { task!(dispatch_the_event_source_event: move || {
let event_source = event_source.root(); let event_source = event_source.root();
if event_source.ready_state.get() != ReadyState::Closed { if event_source.ready_state.get() != ReadyState::Closed {
event.root().upcast::<Event>().fire(&event_source.upcast()); event.root().upcast::<Event>().fire(&event_source.upcast());

View file

@ -416,11 +416,11 @@ fn perform_annotated_read_operation(
) { ) {
// Step 4 // Step 4
let task = FileReadingTask::ProcessRead(filereader.clone(), gen_id); let task = FileReadingTask::ProcessRead(filereader.clone(), gen_id);
task_source.queue_with_canceller(box task, &canceller).unwrap(); task_source.queue_with_canceller(task, &canceller).unwrap();
let task = FileReadingTask::ProcessReadData(filereader.clone(), gen_id); let task = FileReadingTask::ProcessReadData(filereader.clone(), gen_id);
task_source.queue_with_canceller(box task, &canceller).unwrap(); task_source.queue_with_canceller(task, &canceller).unwrap();
let task = FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents); let task = FileReadingTask::ProcessReadEOF(filereader, gen_id, data, blob_contents);
task_source.queue_with_canceller(box task, &canceller).unwrap(); task_source.queue_with_canceller(task, &canceller).unwrap();
} }

View file

@ -70,7 +70,7 @@ impl VirtualMethods for HTMLDetailsElement {
let this = Trusted::new(self); let this = Trusted::new(self);
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = window.dom_manipulation_task_source().queue( let _ = window.dom_manipulation_task_source().queue(
box task!(details_notification_task_steps: move || { task!(details_notification_task_steps: move || {
let this = this.root(); let this = this.root();
if counter == this.toggle_counter.get() { if counter == this.toggle_counter.get() {
this.upcast::<EventTarget>().fire_event(atom!("toggle")); this.upcast::<EventTarget>().fire_event(atom!("toggle"));

View file

@ -440,7 +440,7 @@ impl HTMLFormElement {
let pipeline_id = window.upcast::<GlobalScope>().pipeline_id(); let pipeline_id = window.upcast::<GlobalScope>().pipeline_id();
let script_chan = window.main_thread_script_chan().clone(); let script_chan = window.main_thread_script_chan().clone();
let this = Trusted::new(self); let this = Trusted::new(self);
let task = box task!(navigate_to_form_planned_navigation: move || { let task = task!(navigate_to_form_planned_navigation: move || {
if generation_id != this.root().generation_id.get() { if generation_id != this.root().generation_id.get() {
return; return;
} }

View file

@ -236,7 +236,7 @@ impl HTMLIFrameElement {
let pipeline_id = self.pipeline_id().unwrap(); let pipeline_id = self.pipeline_id().unwrap();
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = window.dom_manipulation_task_source().queue( let _ = window.dom_manipulation_task_source().queue(
box task!(iframe_load_event_steps: move || { task!(iframe_load_event_steps: move || {
this.root().iframe_load_event_steps(pipeline_id); this.root().iframe_load_event_steps(pipeline_id);
}), }),
window.upcast(), window.upcast(),

View file

@ -174,7 +174,7 @@ impl HTMLImageElement {
let image = message.to().unwrap(); let image = message.to().unwrap();
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = task_source.queue_with_canceller( let _ = task_source.queue_with_canceller(
box task!(process_image_response: move || { task!(process_image_response: move || {
let element = element.root(); let element = element.root();
// Ignore any image response for a previous request that has been discarded. // Ignore any image response for a previous request that has been discarded.
if generation == element.generation.get() { if generation == element.generation.get() {
@ -425,7 +425,7 @@ impl HTMLImageElement {
// Step 9. // Step 9.
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = task_source.queue( let _ = task_source.queue(
box task!(image_null_source_error: move || { task!(image_null_source_error: move || {
let this = this.root(); let this = this.root();
{ {
let mut current_request = let mut current_request =
@ -451,7 +451,7 @@ impl HTMLImageElement {
let target = Trusted::new(self.upcast::<EventTarget>()); let target = Trusted::new(self.upcast::<EventTarget>());
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = task_source.queue( let _ = task_source.queue(
box task!(fire_progress_event: move || { task!(fire_progress_event: move || {
let target = target.root(); let target = target.root();
let event = ProgressEvent::new( let event = ProgressEvent::new(
@ -480,7 +480,7 @@ impl HTMLImageElement {
let src = String::from(src); let src = String::from(src);
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = task_source.queue( let _ = task_source.queue(
box task!(image_selected_source_error: move || { task!(image_selected_source_error: move || {
let this = this.root(); let this = this.root();
{ {
let mut current_request = let mut current_request =
@ -549,7 +549,7 @@ impl HTMLImageElement {
let this = Trusted::new(self); let this = Trusted::new(self);
let src = String::from(src); let src = String::from(src);
let _ = window.dom_manipulation_task_source().queue( let _ = window.dom_manipulation_task_source().queue(
box task!(image_load_event: move || { task!(image_load_event: move || {
let this = this.root(); let this = this.root();
{ {
let mut current_request = let mut current_request =

View file

@ -154,7 +154,7 @@ impl HTMLMediaElement {
let target = Trusted::new(self.upcast::<EventTarget>()); let target = Trusted::new(self.upcast::<EventTarget>());
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = window.dom_manipulation_task_source().queue( let _ = window.dom_manipulation_task_source().queue(
box task!(internal_pause_steps: move || { task!(internal_pause_steps: move || {
let target = target.root(); let target = target.root();
// Step 2.3.1. // Step 2.3.1.
@ -186,7 +186,7 @@ impl HTMLMediaElement {
let window = window_from_node(self); let window = window_from_node(self);
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = window.dom_manipulation_task_source().queue( let _ = window.dom_manipulation_task_source().queue(
box task!(notify_about_playing: move || { task!(notify_about_playing: move || {
let target = target.root(); let target = target.root();
// Step 2.1. // Step 2.1.
@ -495,7 +495,7 @@ impl HTMLMediaElement {
let window = window_from_node(self); let window = window_from_node(self);
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = window.dom_manipulation_task_source().queue( let _ = window.dom_manipulation_task_source().queue(
box task!(dedicated_media_source_failure_steps: move || { task!(dedicated_media_source_failure_steps: move || {
let this = this.root(); let this = this.root();
// Step 1. // Step 1.

View file

@ -19,7 +19,7 @@ use js::jsapi::{HandleValue, JSContext};
use script_traits::{ScriptMsg, DOMMessage}; use script_traits::{ScriptMsg, DOMMessage};
use servo_url::ServoUrl; use servo_url::ServoUrl;
use std::cell::Cell; use std::cell::Cell;
use task::TaskBox; use task::TaskOnce;
pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>; pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
@ -104,10 +104,9 @@ impl ServiceWorkerMethods for ServiceWorker {
event_handler!(statechange, GetOnstatechange, SetOnstatechange); event_handler!(statechange, GetOnstatechange, SetOnstatechange);
} }
impl TaskBox for SimpleWorkerErrorHandler<ServiceWorker> { impl TaskOnce for SimpleWorkerErrorHandler<ServiceWorker> {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn run_box(self: Box<Self>) { fn run_once(self) {
let this = *self; ServiceWorker::dispatch_simple_error(self.addr);
ServiceWorker::dispatch_simple_error(this.addr);
} }
} }

View file

@ -167,7 +167,7 @@ impl Storage {
let global = self.global(); let global = self.global();
let this = Trusted::new(self); let this = Trusted::new(self);
global.as_window().dom_manipulation_task_source().queue( global.as_window().dom_manipulation_task_source().queue(
box task!(send_storage_notification: move || { task!(send_storage_notification: move || {
let this = this.root(); let this = this.root();
let global = this.global(); let global = this.global();
let event = StorageEvent::new( let event = StorageEvent::new(

View file

@ -37,7 +37,7 @@ use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
use std::ptr; use std::ptr;
use std::thread; use std::thread;
use task::{TaskBox, TaskCanceller}; use task::{TaskOnce, TaskCanceller};
use task_source::TaskSource; use task_source::TaskSource;
use task_source::networking::NetworkingTaskSource; use task_source::networking::NetworkingTaskSource;
@ -74,7 +74,7 @@ pub fn close_the_websocket_connection(
code: Option<u16>, code: Option<u16>,
reason: String, reason: String,
) { ) {
let close_task = box CloseTask { let close_task = CloseTask {
address: address, address: address,
failed: false, failed: false,
code: code, code: code,
@ -88,7 +88,7 @@ pub fn fail_the_websocket_connection(
task_source: &NetworkingTaskSource, task_source: &NetworkingTaskSource,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) { ) {
let close_task = box CloseTask { let close_task = CloseTask {
address: address, address: address,
failed: true, failed: true,
code: Some(close_code::ABNORMAL), code: Some(close_code::ABNORMAL),
@ -206,14 +206,14 @@ impl WebSocket {
while let Ok(event) = dom_event_receiver.recv() { while let Ok(event) = dom_event_receiver.recv() {
match event { match event {
WebSocketNetworkEvent::ConnectionEstablished { protocol_in_use } => { WebSocketNetworkEvent::ConnectionEstablished { protocol_in_use } => {
let open_thread = box ConnectionEstablishedTask { let open_thread = ConnectionEstablishedTask {
address: address.clone(), address: address.clone(),
protocol_in_use, protocol_in_use,
}; };
task_source.queue_with_canceller(open_thread, &canceller).unwrap(); task_source.queue_with_canceller(open_thread, &canceller).unwrap();
}, },
WebSocketNetworkEvent::MessageReceived(message) => { WebSocketNetworkEvent::MessageReceived(message) => {
let message_thread = box MessageReceivedTask { let message_thread = MessageReceivedTask {
address: address.clone(), address: address.clone(),
message: message, message: message,
}; };
@ -397,9 +397,9 @@ struct ConnectionEstablishedTask {
protocol_in_use: Option<String>, protocol_in_use: Option<String>,
} }
impl TaskBox for ConnectionEstablishedTask { impl TaskOnce for ConnectionEstablishedTask {
/// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established /// https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol:concept-websocket-established
fn run_box(self: Box<Self>) { fn run_once(self) {
let ws = self.address.root(); let ws = self.address.root();
// Step 1. // Step 1.
@ -422,13 +422,13 @@ struct BufferedAmountTask {
address: Trusted<WebSocket>, address: Trusted<WebSocket>,
} }
impl TaskBox for BufferedAmountTask { impl TaskOnce for BufferedAmountTask {
// See https://html.spec.whatwg.org/multipage/#dom-websocket-bufferedamount // See https://html.spec.whatwg.org/multipage/#dom-websocket-bufferedamount
// //
// To be compliant with standards, we need to reset bufferedAmount only when the event loop // To be compliant with standards, we need to reset bufferedAmount only when the event loop
// reaches step 1. In our implementation, the bytes will already have been sent on a background // reaches step 1. In our implementation, the bytes will already have been sent on a background
// thread. // thread.
fn run_box(self: Box<Self>) { fn run_once(self) {
let ws = self.address.root(); let ws = self.address.root();
ws.buffered_amount.set(0); ws.buffered_amount.set(0);
@ -443,8 +443,8 @@ struct CloseTask {
reason: Option<String>, reason: Option<String>,
} }
impl TaskBox for CloseTask { impl TaskOnce for CloseTask {
fn run_box(self: Box<Self>) { fn run_once(self) {
let ws = self.address.root(); let ws = self.address.root();
if ws.ready_state.get() == WebSocketRequestState::Closed { if ws.ready_state.get() == WebSocketRequestState::Closed {
@ -483,9 +483,9 @@ struct MessageReceivedTask {
message: MessageData, message: MessageData,
} }
impl TaskBox for MessageReceivedTask { impl TaskOnce for MessageReceivedTask {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn run_box(self: Box<Self>) { fn run_once(self) {
let ws = self.address.root(); let ws = self.address.root();
debug!("MessageReceivedTask::handler({:p}): readyState={:?}", &*ws, debug!("MessageReceivedTask::handler({:p}): readyState={:?}", &*ws,
ws.ready_state.get()); ws.ready_state.get());

View file

@ -1977,7 +1977,7 @@ impl Window {
serialize_with_transfer_result: StructuredCloneData, serialize_with_transfer_result: StructuredCloneData,
) { ) {
let this = Trusted::new(self); let this = Trusted::new(self);
let task = box task!(post_serialised_message: move || { let task = task!(post_serialised_message: move || {
let this = this.root(); let this = this.root();
// Step 7.1. // Step 7.1.
@ -2012,7 +2012,7 @@ impl Window {
// TODO(#12718): Use the "posted message task source". // TODO(#12718): Use the "posted message task source".
let _ = self.script_chan.send(CommonScriptMsg::Task( let _ = self.script_chan.send(CommonScriptMsg::Task(
ScriptThreadEventCategory::DomEvent, ScriptThreadEventCategory::DomEvent,
self.task_canceller().wrap_task(task), box self.task_canceller().wrap_task(task),
)); ));
} }
} }

View file

@ -28,7 +28,7 @@ use std::cell::Cell;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Sender, channel}; use std::sync::mpsc::{Sender, channel};
use task::TaskBox; use task::TaskOnce;
pub type TrustedWorkerAddress = Trusted<Worker>; pub type TrustedWorkerAddress = Trusted<Worker>;
@ -175,10 +175,9 @@ impl WorkerMethods for Worker {
event_handler!(error, GetOnerror, SetOnerror); event_handler!(error, GetOnerror, SetOnerror);
} }
impl TaskBox for SimpleWorkerErrorHandler<Worker> { impl TaskOnce for SimpleWorkerErrorHandler<Worker> {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn run_box(self: Box<Self>) { fn run_once(self) {
let this = *self; Worker::dispatch_simple_error(self.addr);
Worker::dispatch_simple_error(this.addr);
} }
} }

View file

@ -4,7 +4,7 @@
use net_traits::{Action, FetchResponseListener, FetchResponseMsg}; use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
use task_source::TaskSource; use task_source::TaskSource;
use task_source::networking::NetworkingTaskSource; use task_source::networking::NetworkingTaskSource;
@ -18,7 +18,7 @@ pub struct NetworkListener<Listener: PreInvoke + Send + 'static> {
impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> { impl<Listener: PreInvoke + Send + 'static> NetworkListener<Listener> {
pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) { pub fn notify<A: Action<Listener> + Send + 'static>(&self, action: A) {
let task = box ListenerTask { let task = ListenerTask {
context: self.context.clone(), context: self.context.clone(),
action: action, action: action,
}; };
@ -55,16 +55,15 @@ struct ListenerTask<A: Action<Listener> + Send + 'static, Listener: PreInvoke +
action: A, action: A,
} }
impl<A, Listener> TaskBox for ListenerTask<A, Listener> impl<A, Listener> TaskOnce for ListenerTask<A, Listener>
where where
A: Action<Listener> + Send + 'static, A: Action<Listener> + Send + 'static,
Listener: PreInvoke + Send, Listener: PreInvoke + Send,
{ {
fn run_box(self: Box<Self>) { fn run_once(self) {
let this = *self; let mut context = self.context.lock().unwrap();
let mut context = this.context.lock().unwrap();
if context.should_invoke() { if context.should_invoke() {
this.action.process(&mut *context); self.action.process(&mut *context);
} }
} }
} }

View file

@ -275,7 +275,7 @@ fn queue_settle_promise_for_job(job: &Job, settle: SettleType, task_source: &DOM
let promise = TrustedPromise::new(job.promise.clone()); let promise = TrustedPromise::new(job.promise.clone());
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = task_source.queue( let _ = task_source.queue(
box task!(settle_promise_for_job: move || { task!(settle_promise_for_job: move || {
let promise = promise.root(); let promise = promise.root();
settle_job_promise(&promise.global(), &promise, settle) settle_job_promise(&promise.global(), &promise, settle)
}), }),

View file

@ -13,7 +13,7 @@ macro_rules! task {
($name:ident: move || $body:tt) => {{ ($name:ident: move || $body:tt) => {{
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
struct $name<F>(F); struct $name<F>(F);
impl<F> ::task::TaskBox for $name<F> impl<F> ::task::TaskOnce for $name<F>
where where
F: ::std::ops::FnOnce() + Send, F: ::std::ops::FnOnce() + Send,
{ {
@ -21,7 +21,7 @@ macro_rules! task {
stringify!($name) stringify!($name)
} }
fn run_box(self: Box<Self>) { fn run_once(self) {
(self.0)(); (self.0)();
} }
} }
@ -30,14 +30,35 @@ macro_rules! task {
} }
/// A task that can be run. The name method is for profiling purposes. /// A task that can be run. The name method is for profiling purposes.
/// pub trait TaskOnce: Send {
/// All tasks must be boxed to be run.
pub trait TaskBox: Send {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn name(&self) -> &'static str { unsafe { intrinsics::type_name::<Self>() } } fn name(&self) -> &'static str {
unsafe { intrinsics::type_name::<Self>() }
}
fn run_once(self);
}
/// A boxed version of `TaskOnce`.
pub trait TaskBox: Send {
fn name(&self) -> &'static str;
fn run_box(self: Box<Self>); fn run_box(self: Box<Self>);
} }
impl<T> TaskBox for T
where
T: TaskOnce,
{
fn name(&self) -> &'static str {
TaskOnce::name(self)
}
fn run_box(self: Box<Self>) {
self.run_once()
}
}
impl fmt::Debug for TaskBox { impl fmt::Debug for TaskBox {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_tuple(self.name()).field(&format_args!("...")).finish() fmt.debug_tuple(self.name()).field(&format_args!("...")).finish()
@ -52,11 +73,11 @@ pub struct TaskCanceller {
impl TaskCanceller { impl TaskCanceller {
/// Returns a wrapped `task` that will be cancelled if the `TaskCanceller` /// Returns a wrapped `task` that will be cancelled if the `TaskCanceller`
/// says so. /// says so.
pub fn wrap_task<T>(&self, task: Box<T>) -> Box<TaskBox> pub fn wrap_task<T>(&self, task: T) -> impl TaskOnce
where where
T: TaskBox + 'static, T: TaskOnce,
{ {
box CancellableTask { CancellableTask {
cancelled: self.cancelled.clone(), cancelled: self.cancelled.clone(),
inner: task, inner: task,
} }
@ -64,14 +85,14 @@ impl TaskCanceller {
} }
/// A task that can be cancelled by toggling a shared flag. /// A task that can be cancelled by toggling a shared flag.
pub struct CancellableTask<T: TaskBox> { pub struct CancellableTask<T: TaskOnce> {
cancelled: Option<Arc<AtomicBool>>, cancelled: Option<Arc<AtomicBool>>,
inner: Box<T>, inner: T,
} }
impl<T> CancellableTask<T> impl<T> CancellableTask<T>
where where
T: TaskBox, T: TaskOnce,
{ {
fn is_cancelled(&self) -> bool { fn is_cancelled(&self) -> bool {
self.cancelled.as_ref().map_or(false, |cancelled| { self.cancelled.as_ref().map_or(false, |cancelled| {
@ -80,17 +101,17 @@ where
} }
} }
impl<T> TaskBox for CancellableTask<T> impl<T> TaskOnce for CancellableTask<T>
where where
T: TaskBox, T: TaskOnce,
{ {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
self.inner.name() self.inner.name()
} }
fn run_box(self: Box<Self>) { fn run_once(self) {
if !self.is_cancelled() { if !self.is_cancelled() {
self.inner.run_box() self.inner.run_once()
} }
} }
} }

View file

@ -13,7 +13,7 @@ use servo_atoms::Atom;
use std::fmt; use std::fmt;
use std::result::Result; use std::result::Result;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
use task_source::TaskSource; use task_source::TaskSource;
#[derive(Clone, JSTraceable)] #[derive(Clone, JSTraceable)]
@ -28,15 +28,15 @@ impl fmt::Debug for DOMManipulationTaskSource {
impl TaskSource for DOMManipulationTaskSource { impl TaskSource for DOMManipulationTaskSource {
fn queue_with_canceller<T>( fn queue_with_canceller<T>(
&self, &self,
msg: Box<T>, task: T,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) -> Result<(), ()> ) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task( let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task(
ScriptThreadEventCategory::ScriptEvent, ScriptThreadEventCategory::ScriptEvent,
canceller.wrap_task(msg), box canceller.wrap_task(task),
)); ));
self.0.send(msg).map_err(|_| ()) self.0.send(msg).map_err(|_| ())
} }
@ -50,7 +50,7 @@ impl DOMManipulationTaskSource {
cancelable: EventCancelable, cancelable: EventCancelable,
window: &Window) { window: &Window) {
let target = Trusted::new(target); let target = Trusted::new(target);
let task = box EventTask { let task = EventTask {
target: target, target: target,
name: name, name: name,
bubbles: bubbles, bubbles: bubbles,
@ -61,6 +61,6 @@ impl DOMManipulationTaskSource {
pub fn queue_simple_event(&self, target: &EventTarget, name: Atom, window: &Window) { pub fn queue_simple_event(&self, target: &EventTarget, name: Atom, window: &Window) {
let target = Trusted::new(target); let target = Trusted::new(target);
let _ = self.queue(box SimpleEventTask { target, name }, window.upcast()); let _ = self.queue(SimpleEventTask { target, name }, window.upcast());
} }
} }

View file

@ -6,7 +6,7 @@ use dom::domexception::DOMErrorName;
use dom::filereader::{FileReader, TrustedFileReader, GenerationId, ReadMetaData}; use dom::filereader::{FileReader, TrustedFileReader, GenerationId, ReadMetaData};
use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory, ScriptChan}; use script_runtime::{CommonScriptMsg, ScriptThreadEventCategory, ScriptChan};
use std::sync::Arc; use std::sync::Arc;
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
use task_source::TaskSource; use task_source::TaskSource;
#[derive(JSTraceable)] #[derive(JSTraceable)]
@ -21,21 +21,21 @@ impl Clone for FileReadingTaskSource {
impl TaskSource for FileReadingTaskSource { impl TaskSource for FileReadingTaskSource {
fn queue_with_canceller<T>( fn queue_with_canceller<T>(
&self, &self,
msg: Box<T>, task: T,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) -> Result<(), ()> ) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
self.0.send(CommonScriptMsg::Task( self.0.send(CommonScriptMsg::Task(
ScriptThreadEventCategory::FileRead, ScriptThreadEventCategory::FileRead,
canceller.wrap_task(msg), box canceller.wrap_task(task),
)) ))
} }
} }
impl TaskBox for FileReadingTask { impl TaskOnce for FileReadingTask {
fn run_box(self: Box<Self>) { fn run_once(self) {
self.handle_task(); self.handle_task();
} }
} }

View file

@ -11,21 +11,21 @@ pub mod user_interaction;
use dom::globalscope::GlobalScope; use dom::globalscope::GlobalScope;
use std::result::Result; use std::result::Result;
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
pub trait TaskSource { pub trait TaskSource {
fn queue_with_canceller<T>( fn queue_with_canceller<T>(
&self, &self,
msg: Box<T>, task: T,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) -> Result<(), ()> ) -> Result<(), ()>
where where
T: TaskBox + 'static; T: TaskOnce + 'static;
fn queue<T>(&self, msg: Box<T>, global: &GlobalScope) -> Result<(), ()> fn queue<T>(&self, task: T, global: &GlobalScope) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
self.queue_with_canceller(msg, &global.task_canceller()) self.queue_with_canceller(task, &global.task_canceller())
} }
} }

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
use task_source::TaskSource; use task_source::TaskSource;
#[derive(JSTraceable)] #[derive(JSTraceable)]
@ -18,15 +18,15 @@ impl Clone for NetworkingTaskSource {
impl TaskSource for NetworkingTaskSource { impl TaskSource for NetworkingTaskSource {
fn queue_with_canceller<T>( fn queue_with_canceller<T>(
&self, &self,
msg: Box<T>, task: T,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) -> Result<(), ()> ) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
self.0.send(CommonScriptMsg::Task( self.0.send(CommonScriptMsg::Task(
ScriptThreadEventCategory::NetworkEvent, ScriptThreadEventCategory::NetworkEvent,
canceller.wrap_task(msg), box canceller.wrap_task(task),
)) ))
} }
} }
@ -34,10 +34,13 @@ impl TaskSource for NetworkingTaskSource {
impl NetworkingTaskSource { impl NetworkingTaskSource {
/// This queues a task that will not be cancelled when its associated /// This queues a task that will not be cancelled when its associated
/// global scope gets destroyed. /// global scope gets destroyed.
pub fn queue_unconditionally<T>(&self, msg: Box<T>) -> Result<(), ()> pub fn queue_unconditionally<T>(&self, task: T) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
self.0.send(CommonScriptMsg::Task(ScriptThreadEventCategory::NetworkEvent, msg)) self.0.send(CommonScriptMsg::Task(
ScriptThreadEventCategory::NetworkEvent,
box task,
))
} }
} }

View file

@ -11,7 +11,7 @@ use dom::globalscope::GlobalScope;
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
use std::fmt; use std::fmt;
use std::result::Result; use std::result::Result;
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
use task_source::TaskSource; use task_source::TaskSource;
#[derive(JSTraceable)] #[derive(JSTraceable)]
@ -32,15 +32,15 @@ impl fmt::Debug for PerformanceTimelineTaskSource {
impl TaskSource for PerformanceTimelineTaskSource { impl TaskSource for PerformanceTimelineTaskSource {
fn queue_with_canceller<T>( fn queue_with_canceller<T>(
&self, &self,
msg: Box<T>, task: T,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) -> Result<(), ()> ) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
let msg = CommonScriptMsg::Task( let msg = CommonScriptMsg::Task(
ScriptThreadEventCategory::PerformanceTimelineTask, ScriptThreadEventCategory::PerformanceTimelineTask,
canceller.wrap_task(msg) box canceller.wrap_task(task)
); );
self.0.send(msg).map_err(|_| ()) self.0.send(msg).map_err(|_| ())
} }
@ -51,7 +51,7 @@ impl PerformanceTimelineTaskSource {
let owner = Trusted::new(&*global.performance()); let owner = Trusted::new(&*global.performance());
// FIXME(nox): Why are errors silenced here? // FIXME(nox): Why are errors silenced here?
let _ = self.queue( let _ = self.queue(
box task!(notify_performance_observers: move || { task!(notify_performance_observers: move || {
owner.root().notify_observers(); owner.root().notify_observers();
}), }),
global, global,

View file

@ -13,7 +13,7 @@ use servo_atoms::Atom;
use std::fmt; use std::fmt;
use std::result::Result; use std::result::Result;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use task::{TaskBox, TaskCanceller}; use task::{TaskCanceller, TaskOnce};
use task_source::TaskSource; use task_source::TaskSource;
#[derive(Clone, JSTraceable)] #[derive(Clone, JSTraceable)]
@ -28,15 +28,15 @@ impl fmt::Debug for UserInteractionTaskSource {
impl TaskSource for UserInteractionTaskSource { impl TaskSource for UserInteractionTaskSource {
fn queue_with_canceller<T>( fn queue_with_canceller<T>(
&self, &self,
msg: Box<T>, task: T,
canceller: &TaskCanceller, canceller: &TaskCanceller,
) -> Result<(), ()> ) -> Result<(), ()>
where where
T: TaskBox + 'static, T: TaskOnce + 'static,
{ {
let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task( let msg = MainThreadScriptMsg::Common(CommonScriptMsg::Task(
ScriptThreadEventCategory::InputEvent, ScriptThreadEventCategory::InputEvent,
canceller.wrap_task(msg), box canceller.wrap_task(task),
)); ));
self.0.send(msg).map_err(|_| ()) self.0.send(msg).map_err(|_| ())
} }
@ -50,7 +50,7 @@ impl UserInteractionTaskSource {
cancelable: EventCancelable, cancelable: EventCancelable,
window: &Window) { window: &Window) {
let target = Trusted::new(target); let target = Trusted::new(target);
let task = box EventTask { target, name, bubbles, cancelable }; let task = EventTask { target, name, bubbles, cancelable };
let _ = self.queue(task, window.upcast()); let _ = self.queue(task, window.upcast());
} }
} }