Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

script: Make timer events e10s-safe. #8492

Merged
merged 1 commit into from Nov 13, 2015
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

script: Make timer events e10s-safe.

Closes #8235.
  • Loading branch information
pcwalton authored and jdm committed Nov 12, 2015
commit 1dc0d61c3cfbfbb856c970e9bb4e72f45837a457
@@ -148,7 +148,7 @@ pub struct Constellation<LTF, STF> {
/// A list of in-process senders to `WebGLPaintTask`s.
webgl_paint_tasks: Vec<Sender<CanvasMsg>>,

scheduler_chan: Sender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerEventRequest>,
}

/// State needed to construct a constellation.
@@ -68,6 +68,9 @@ pub struct CompositionPipeline {
}

/// Initial setup data needed to construct a pipeline.
///
/// *DO NOT* add any Senders to this unless you absolutely know what you're doing, or pcwalton will
/// have to rewrite your code. Use IPC senders instead.
pub struct InitialPipelineState {
/// The ID of the pipeline to create.
pub id: PipelineId,
@@ -77,7 +80,7 @@ pub struct InitialPipelineState {
/// A channel to the associated constellation.
pub constellation_chan: ConstellationChan,
/// A channel to schedule timer events.
pub scheduler_chan: Sender<TimerEventRequest>,
pub scheduler_chan: IpcSender<TimerEventRequest>,
/// A channel to the compositor.
pub compositor_proxy: Box<CompositorProxy + 'static + Send>,
/// A channel to the developer tools, if applicable.
@@ -315,7 +318,7 @@ pub struct PipelineContent {
id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>,
constellation_chan: ConstellationChan,
scheduler_chan: Sender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerEventRequest>,
compositor_proxy: Box<CompositorProxy + Send + 'static>,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
image_cache_task: ImageCacheTask,
@@ -3,6 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use euclid::length::Length;
use ipc_channel::ipc::{self, IpcSender};
use ipc_channel::router::ROUTER;
use num::traits::Saturating;
use script_traits::{MsDuration, NsDuration, precise_time_ms, precise_time_ns};
use script_traits::{TimerEvent, TimerEventRequest};
@@ -11,7 +13,7 @@ use std::cmp::{self, Ord};
use std::collections::BinaryHeap;
use std::sync::Arc;
use std::sync::atomic::{self, AtomicBool};
use std::sync::mpsc::{channel, Receiver, Select, Sender};
use std::sync::mpsc::{channel, Receiver, Select};
use std::thread::{self, spawn, Thread};
use util::task::spawn_named;

@@ -107,11 +109,11 @@ enum Task {
}

impl TimerScheduler {
pub fn start() -> Sender<TimerEventRequest> {
let (chan, port) = channel();
pub fn start() -> IpcSender<TimerEventRequest> {
let (chan, port) = ipc::channel().unwrap();

let timer_scheduler = TimerScheduler {
port: port,
port: ROUTER.route_ipc_receiver_to_new_mpsc_receiver(port),

scheduled_events: RefCell::new(BinaryHeap::new()),

@@ -169,3 +169,4 @@ pub enum EventResult {
DefaultAllowed,
DefaultPrevented,
}

@@ -23,7 +23,6 @@ use net_traits::ResourceTask;
use profile_traits::mem;
use script_task::{CommonScriptMsg, ScriptChan, ScriptPort, ScriptTask};
use script_traits::{MsDuration, TimerEventRequest};
use std::sync::mpsc::Sender;
use timers::{ScheduledCallback, TimerHandle};
use url::Url;
use util::mem::HeapSizeOf;
@@ -100,7 +99,7 @@ impl<'a> GlobalRef<'a> {
}

/// Get the scheduler channel to request timer events.
pub fn scheduler_chan(&self) -> Sender<TimerEventRequest> {
pub fn scheduler_chan(&self) -> IpcSender<TimerEventRequest> {
match *self {
GlobalRef::Window(window) => window.scheduler_chan(),
GlobalRef::Worker(worker) => worker.scheduler_chan(),
@@ -62,7 +62,7 @@ use net_traits::storage_task::StorageType;
use profile_traits::mem::ProfilerChan as MemProfilerChan;
use profile_traits::time::ProfilerChan as TimeProfilerChan;
use script_task::ScriptChan;
use script_traits::{TimerEventChan, TimerEventId, TimerSource, UntrustedNodeAddress};
use script_traits::{TimerEventId, TimerSource, UntrustedNodeAddress};
use selectors::parser::PseudoElement;
use selectors::states::*;
use serde::{Deserialize, Serialize};
@@ -302,13 +302,6 @@ impl JSTraceable for Box<ScriptChan + Send> {
}
}

impl JSTraceable for Box<TimerEventChan + Send> {
#[inline]
fn trace(&self, _trc: *mut JSTracer) {
// Do nothing
}
}

impl JSTraceable for Box<FnBox(f64, )> {
#[inline]
fn trace(&self, _trc: *mut JSTracer) {
@@ -19,7 +19,7 @@ use dom::messageevent::MessageEvent;
use dom::worker::{SimpleWorkerErrorHandler, TrustedWorkerAddress, WorkerMessageHandler};
use dom::workerglobalscope::WorkerGlobalScope;
use dom::workerglobalscope::WorkerGlobalScopeInit;
use ipc_channel::ipc::IpcReceiver;
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use js::jsapi::{HandleValue, JSContext, RootedValue};
use js::jsapi::{JSAutoCompartment, JSAutoRequest};
@@ -30,7 +30,7 @@ use net_traits::load_whole_resource;
use rand::random;
use script_task::ScriptTaskEventCategory::WorkerEvent;
use script_task::{ScriptTask, ScriptChan, ScriptPort, StackRootTLS, CommonScriptMsg};
use script_traits::{TimerEvent, TimerEventChan, TimerSource};
use script_traits::{TimerEvent, TimerSource};
use std::mem::replace;
use std::rc::Rc;
use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel};
@@ -103,29 +103,6 @@ impl ScriptPort for Receiver<(TrustedWorkerAddress, WorkerScriptMsg)> {
}
}

/// A TimerEventChan that can be cloned freely and will silently send a TrustedWorkerAddress
/// with timer events. While this SendableWorkerScriptChan is alive, the associated Worker
/// object will remain alive.
struct WorkerThreadTimerEventChan {
sender: Sender<(TrustedWorkerAddress, TimerEvent)>,
worker: TrustedWorkerAddress,
}

impl TimerEventChan for WorkerThreadTimerEventChan {
fn send(&self, event: TimerEvent) -> Result<(), ()> {
self.sender
.send((self.worker.clone(), event))
.map_err(|_| ())
}

fn clone(&self) -> Box<TimerEventChan + Send> {
box WorkerThreadTimerEventChan {
sender: self.sender.clone(),
worker: self.worker.clone(),
}
}
}

/// Set the `worker` field of a related DedicatedWorkerGlobalScope object to a particular
/// value for the duration of this object's lifetime. This ensures that the related Worker
/// object only lives as long as necessary (ie. while events are being executed), while
@@ -183,7 +160,7 @@ impl DedicatedWorkerGlobalScope {
parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: Box<TimerEventChan + Send>,
timer_event_chan: IpcSender<TimerEvent>,
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
-> DedicatedWorkerGlobalScope {

@@ -207,7 +184,7 @@ impl DedicatedWorkerGlobalScope {
parent_sender: Box<ScriptChan + Send>,
own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>,
timer_event_chan: Box<TimerEventChan + Send>,
timer_event_chan: IpcSender<TimerEvent>,
timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>)
-> Root<DedicatedWorkerGlobalScope> {
let scope = box DedicatedWorkerGlobalScope::new_inherited(
@@ -249,15 +226,17 @@ impl DedicatedWorkerGlobalScope {
ROUTER.route_ipc_receiver_to_mpsc_sender(from_devtools_receiver, devtools_mpsc_chan);

let (timer_tx, timer_rx) = channel();
let timer_event_chan = box WorkerThreadTimerEventChan {
sender: timer_tx,
worker: worker.clone(),
};
let (timer_ipc_chan, timer_ipc_port) = ipc::channel().unwrap();
let worker_for_route = worker.clone();
ROUTER.add_route(timer_ipc_port.to_opaque(), box move |message| {
let event = message.to().unwrap();
timer_tx.send((worker_for_route.clone(), event)).unwrap();
});

let global = DedicatedWorkerGlobalScope::new(
init, url, id, devtools_mpsc_port, runtime.clone(),
parent_sender.clone(), own_sender, receiver,
timer_event_chan, timer_rx);
timer_ipc_chan, timer_rx);
// FIXME(njn): workers currently don't have a unique ID suitable for using in reporter
// registration (#6631), so we instead use a random number and cross our fingers.
let scope = global.upcast::<WorkerGlobalScope>();
@@ -53,8 +53,8 @@ use page::Page;
use profile_traits::mem;
use rustc_serialize::base64::{FromBase64, STANDARD, ToBase64};
use script_task::{ScriptChan, ScriptPort, MainThreadScriptMsg, RunnableWrapper};
use script_task::{SendableMainThreadScriptChan, MainThreadScriptChan, MainThreadTimerEventChan};
use script_traits::{MsDuration, TimerEventChan, TimerEventId, TimerEventRequest, TimerSource};
use script_task::{SendableMainThreadScriptChan, MainThreadScriptChan};
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use selectors::parser::PseudoElement;
use std::ascii::AsciiExt;
use std::borrow::ToOwned;
@@ -129,7 +129,7 @@ pub struct Window {
session_storage: MutNullableHeap<JS<Storage>>,
local_storage: MutNullableHeap<JS<Storage>>,
#[ignore_heap_size_of = "channels are hard"]
scheduler_chan: Sender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerEventRequest>,
timers: ActiveTimers,

next_worker_id: Cell<WorkerId>,
@@ -1077,7 +1077,7 @@ impl Window {
self.constellation_chan.clone()
}

pub fn scheduler_chan(&self) -> Sender<TimerEventRequest> {
pub fn scheduler_chan(&self) -> IpcSender<TimerEventRequest> {
self.scheduler_chan.clone()
}

@@ -1227,8 +1227,8 @@ impl Window {
mem_profiler_chan: mem::ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
constellation_chan: ConstellationChan,
scheduler_chan: Sender<TimerEventRequest>,
timer_event_chan: MainThreadTimerEventChan,
scheduler_chan: IpcSender<TimerEventRequest>,
timer_event_chan: IpcSender<TimerEvent>,
layout_chan: LayoutChan,
id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>,
@@ -1261,7 +1261,7 @@ impl Window {
session_storage: Default::default(),
local_storage: Default::default(),
scheduler_chan: scheduler_chan.clone(),
timers: ActiveTimers::new(box timer_event_chan, scheduler_chan),
timers: ActiveTimers::new(timer_event_chan, scheduler_chan),
next_worker_id: Cell::new(WorkerId(0)),
id: id,
parent_info: parent_info,
@@ -24,11 +24,11 @@ use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};
use net_traits::{ResourceTask, load_whole_resource};
use profile_traits::mem;
use script_task::{CommonScriptMsg, ScriptChan, ScriptPort};
use script_traits::{MsDuration, TimerEventChan, TimerEventId, TimerEventRequest, TimerSource};
use script_traits::{MsDuration, TimerEvent, TimerEventId, TimerEventRequest, TimerSource};
use std::cell::Cell;
use std::default::Default;
use std::rc::Rc;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::mpsc::Receiver;
use timers::{ActiveTimers, IsInterval, ScheduledCallback, TimerCallback, TimerHandle};
use url::{Url, UrlParser};
use util::str::DOMString;
@@ -44,7 +44,7 @@ pub struct WorkerGlobalScopeInit {
pub to_devtools_sender: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
pub from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
pub constellation_chan: ConstellationChan,
pub scheduler_chan: Sender<TimerEventRequest>,
pub scheduler_chan: IpcSender<TimerEventRequest>,
pub worker_id: WorkerId,
}

@@ -87,15 +87,15 @@ pub struct WorkerGlobalScope {
constellation_chan: ConstellationChan,

#[ignore_heap_size_of = "Defined in std"]
scheduler_chan: Sender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerEventRequest>,
}

impl WorkerGlobalScope {
pub fn new_inherited(init: WorkerGlobalScopeInit,
worker_url: Url,
runtime: Rc<Runtime>,
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
timer_event_chan: Box<TimerEventChan + Send>)
timer_event_chan: IpcSender<TimerEvent>)
-> WorkerGlobalScope {
WorkerGlobalScope {
eventtarget: EventTarget::new_inherited(),
@@ -139,7 +139,7 @@ impl WorkerGlobalScope {
self.constellation_chan.clone()
}

pub fn scheduler_chan(&self) -> Sender<TimerEventRequest> {
pub fn scheduler_chan(&self) -> IpcSender<TimerEventRequest> {
self.scheduler_chan.clone()
}

@@ -83,7 +83,7 @@ use script_traits::CompositorEvent::{MouseDownEvent, MouseUpEvent, TouchEvent};
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 script_traits::{TimerEvent, TimerEventRequest, TimerSource};
use script_traits::{TouchEventType, TouchId};
use std::any::Any;
use std::borrow::ToOwned;
@@ -353,20 +353,6 @@ 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<'a>(PhantomData<&'a u32>);

impl<'a> StackRootTLS<'a> {
@@ -449,7 +435,7 @@ pub struct ScriptTask {
/// List of pipelines that have been owned and closed by this script task.
closed_pipelines: DOMRefCell<HashSet<PipelineId>>,

scheduler_chan: Sender<TimerEventRequest>,
scheduler_chan: IpcSender<TimerEventRequest>,
timer_event_chan: Sender<TimerEvent>,
timer_event_port: Receiver<TimerEvent>,
}
@@ -1607,6 +1593,10 @@ impl ScriptTask {
let mut page_remover = AutoPageRemover::new(self, page_to_remove);
let MainThreadScriptChan(ref sender) = self.chan;

let (ipc_timer_event_chan, ipc_timer_event_port) = ipc::channel().unwrap();
ROUTER.route_ipc_receiver_to_mpsc_sender(ipc_timer_event_port,
self.timer_event_chan.clone());

// Create the window and document objects.
let window = Window::new(self.js_runtime.clone(),
page.clone(),
@@ -1620,7 +1610,7 @@ impl ScriptTask {
self.devtools_chan.clone(),
self.constellation_chan.clone(),
self.scheduler_chan.clone(),
MainThreadTimerEventChan(self.timer_event_chan.clone()),
ipc_timer_event_chan,
incomplete.layout_chan,
incomplete.pipeline_id,
incomplete.parent_info,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.