aboutsummaryrefslogtreecommitdiffstats
path: root/components/util
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2015-07-31 09:43:40 -0600
committerbors-servo <metajack+bors@gmail.com>2015-07-31 09:43:40 -0600
commitc4480b5d0309acc7f154166b91992f73a85de57f (patch)
tree494001ef3527c23854439ddca953a7443025712c /components/util
parent33bc16fe353be237855d006b34e96fbe59f24846 (diff)
parent17ead8716b53715086c990dc16e20e1cf6462c16 (diff)
downloadservo-c4480b5d0309acc7f154166b91992f73a85de57f.tar.gz
servo-c4480b5d0309acc7f154166b91992f73a85de57f.zip
Auto merge of #6795 - pcwalton:display-list-e10s-fixes, r=glennw
Send display lists over IPC in multiprocess mode. This patch set introduces the `--multiprocess` (`-M`) switch. Right now, all it does it cause display lists to be serialized, but eventually it will cause actual processes to be spawned. r? @metajack <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6795) <!-- Reviewable:end -->
Diffstat (limited to 'components/util')
-rw-r--r--components/util/Cargo.toml3
-rw-r--r--components/util/ipc.rs94
-rw-r--r--components/util/lib.rs2
-rw-r--r--components/util/linked_list.rs73
-rw-r--r--components/util/opts.rs6
5 files changed, 105 insertions, 73 deletions
diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml
index a61600c8d5a..6558792b21b 100644
--- a/components/util/Cargo.toml
+++ b/components/util/Cargo.toml
@@ -25,6 +25,9 @@ git = "https://github.com/servo/rust-azure"
version = "0.3"
features = [ "serde-serialization" ]
+[dependencies.ipc-channel]
+git = "https://github.com/pcwalton/ipc-channel"
+
[dependencies]
log = "0.3"
bitflags = "0.3"
diff --git a/components/util/ipc.rs b/components/util/ipc.rs
new file mode 100644
index 00000000000..7e47ff696f7
--- /dev/null
+++ b/components/util/ipc.rs
@@ -0,0 +1,94 @@
+/* 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 http://mozilla.org/MPL/2.0/. */
+
+use opts;
+
+use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::router::ROUTER;
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use std::any::Any;
+use std::collections::HashMap;
+use std::sync::Mutex;
+use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
+use std::sync::mpsc::{self, Receiver, Sender};
+
+lazy_static! {
+ static ref IN_PROCESS_SENDERS: Mutex<HashMap<usize,Box<Any + Send>>> =
+ Mutex::new(HashMap::new());
+}
+
+static NEXT_SENDER_ID: AtomicUsize = ATOMIC_USIZE_INIT;
+
+pub enum OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
+ OutOfProcess(IpcSender<T>),
+ InProcess(Sender<T>),
+}
+
+impl<T> OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
+ pub fn send(&self, value: T) -> Result<(),()> {
+ match *self {
+ OptionalIpcSender::OutOfProcess(ref ipc_sender) => ipc_sender.send(value),
+ OptionalIpcSender::InProcess(ref sender) => sender.send(value).map_err(|_| ()),
+ }
+ }
+}
+
+impl<T> Clone for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
+ fn clone(&self) -> OptionalIpcSender<T> {
+ match *self {
+ OptionalIpcSender::OutOfProcess(ref ipc_sender) => {
+ OptionalIpcSender::OutOfProcess((*ipc_sender).clone())
+ }
+ OptionalIpcSender::InProcess(ref sender) => {
+ OptionalIpcSender::InProcess((*sender).clone())
+ }
+ }
+ }
+}
+
+impl<T> Deserialize for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
+ fn deserialize<D>(deserializer: &mut D)
+ -> Result<OptionalIpcSender<T>,D::Error> where D: Deserializer {
+ if opts::get().multiprocess {
+ return Ok(OptionalIpcSender::OutOfProcess(try!(Deserialize::deserialize(
+ deserializer))))
+ }
+ let id: usize = try!(Deserialize::deserialize(deserializer));
+ let sender = (*IN_PROCESS_SENDERS.lock()
+ .unwrap()
+ .remove(&id)
+ .unwrap()
+ .downcast_ref::<Sender<T>>()
+ .unwrap()).clone();
+ Ok(OptionalIpcSender::InProcess(sender))
+ }
+}
+
+impl<T> Serialize for OptionalIpcSender<T> where T: Deserialize + Serialize + Send + Any {
+ fn serialize<S>(&self, serializer: &mut S) -> Result<(),S::Error> where S: Serializer {
+ match *self {
+ OptionalIpcSender::OutOfProcess(ref ipc_sender) => ipc_sender.serialize(serializer),
+ OptionalIpcSender::InProcess(ref sender) => {
+ let id = NEXT_SENDER_ID.fetch_add(1, Ordering::SeqCst);
+ IN_PROCESS_SENDERS.lock()
+ .unwrap()
+ .insert(id, Box::new((*sender).clone()) as Box<Any + Send>);
+ id.serialize(serializer)
+ }
+ }
+ }
+}
+
+pub fn optional_ipc_channel<T>() -> (OptionalIpcSender<T>, Receiver<T>)
+ where T: Deserialize + Serialize + Send + Any {
+ if opts::get().multiprocess {
+ let (ipc_sender, ipc_receiver) = ipc::channel().unwrap();
+ let receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_receiver);
+ (OptionalIpcSender::OutOfProcess(ipc_sender), receiver)
+ } else {
+ let (sender, receiver) = mpsc::channel();
+ (OptionalIpcSender::InProcess(sender), receiver)
+ }
+}
+
diff --git a/components/util/lib.rs b/components/util/lib.rs
index b108c516acc..8db4b17f5ec 100644
--- a/components/util/lib.rs
+++ b/components/util/lib.rs
@@ -31,6 +31,7 @@ extern crate alloc;
#[macro_use] extern crate cssparser;
extern crate euclid;
extern crate getopts;
+extern crate ipc_channel;
extern crate libc;
extern crate num as num_lib;
extern crate num_cpus;
@@ -49,6 +50,7 @@ pub mod debug_utils;
pub mod deque;
pub mod linked_list;
pub mod geometry;
+pub mod ipc;
pub mod logical_geometry;
pub mod mem;
pub mod opts;
diff --git a/components/util/linked_list.rs b/components/util/linked_list.rs
index bf20f434d54..5114f02c0e4 100644
--- a/components/util/linked_list.rs
+++ b/components/util/linked_list.rs
@@ -4,81 +4,8 @@
//! Utility functions for doubly-linked lists.
-use mem::HeapSizeOf;
-
-use serde::de::{Error, SeqVisitor, Visitor};
-use serde::ser::impls::SeqIteratorVisitor;
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::LinkedList;
-use std::marker::PhantomData;
use std::mem;
-use std::ops::{Deref, DerefMut};
-
-pub struct SerializableLinkedList<T>(LinkedList<T>);
-
-impl<T> SerializableLinkedList<T> {
- pub fn new(linked_list: LinkedList<T>) -> SerializableLinkedList<T> {
- SerializableLinkedList(linked_list)
- }
-}
-
-impl<T> Deref for SerializableLinkedList<T> {
- type Target = LinkedList<T>;
-
- fn deref(&self) -> &LinkedList<T> {
- &self.0
- }
-}
-
-impl<T> DerefMut for SerializableLinkedList<T> {
- fn deref_mut(&mut self) -> &mut LinkedList<T> {
- &mut self.0
- }
-}
-
-impl<T: HeapSizeOf> HeapSizeOf for SerializableLinkedList<T> {
- fn heap_size_of_children(&self) -> usize {
- self.0.heap_size_of_children()
- }
-}
-
-impl<T> Serialize for SerializableLinkedList<T> where T: Serialize {
- fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
- serializer.visit_seq(SeqIteratorVisitor::new(self.0.iter(), Some(self.0.len())))
- }
-}
-
-impl<T> Deserialize for SerializableLinkedList<T> where T: Deserialize {
- fn deserialize<D>(deserializer: &mut D) -> Result<SerializableLinkedList<T>, D::Error>
- where D: Deserializer {
- struct SerializableLinkedListVisitor<T> {
- marker: PhantomData<T>,
- }
-
- impl<T> Visitor for SerializableLinkedListVisitor<T> where T: Deserialize {
- type Value = SerializableLinkedList<T>;
-
- #[inline]
- fn visit_seq<V>(&mut self, mut visitor: V)
- -> Result<SerializableLinkedList<T>, V::Error>
- where V: SeqVisitor {
- let mut list = LinkedList::new();
- for _ in 0..visitor.size_hint().0 {
- match try!(visitor.visit()) {
- Some(element) => list.push_back(element),
- None => return Err(Error::end_of_stream_error()),
- }
- }
- try!(visitor.end());
- Ok(SerializableLinkedList(list))
- }
- }
-
- deserializer.visit_seq(SerializableLinkedListVisitor {
- marker: PhantomData,
- })
- }
-}
/// Splits the head off a list in O(1) time, and returns the head.
pub fn split_off_head<T>(list: &mut LinkedList<T>) -> LinkedList<T> {
diff --git a/components/util/opts.rs b/components/util/opts.rs
index c8f65c97e54..efc580bd5e6 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -132,6 +132,9 @@ pub struct Opts {
/// An optional string allowing the user agent to be set for testing.
pub user_agent: Option<String>,
+ /// Whether to run in multiprocess mode.
+ pub multiprocess: bool,
+
/// Dumps the flow tree after a layout.
pub dump_flow_tree: bool,
@@ -251,6 +254,7 @@ pub fn default_opts() -> Opts {
webdriver_port: None,
initial_window_size: Size2D::typed(800, 600),
user_agent: None,
+ multiprocess: false,
dump_flow_tree: false,
dump_display_list: false,
dump_display_list_json: false,
@@ -291,6 +295,7 @@ pub fn from_cmdline_args(args: &[String]) {
getopts::optflagopt("", "webdriver", "Start remote WebDriver server on port", "7000"),
getopts::optopt("", "resolution", "Set window resolution.", "800x600"),
getopts::optopt("u", "user-agent", "Set custom user agent string", "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)"),
+ getopts::optflag("M", "multiprocess", "Run in multiprocess mode"),
getopts::optopt("Z", "debug",
"A comma-separated string of debug options. Pass help to show available options.", ""),
getopts::optflag("h", "help", "Print this message"),
@@ -421,6 +426,7 @@ pub fn from_cmdline_args(args: &[String]) {
webdriver_port: webdriver_port,
initial_window_size: initial_window_size,
user_agent: opt_match.opt_str("u"),
+ multiprocess: opt_match.opt_present("M"),
show_debug_borders: debug_options.contains(&"show-compositor-borders"),
show_debug_fragment_borders: debug_options.contains(&"show-fragment-borders"),
show_debug_parallel_paint: debug_options.contains(&"show-parallel-paint"),