diff options
Diffstat (limited to 'components/util')
-rw-r--r-- | components/util/Cargo.toml | 3 | ||||
-rw-r--r-- | components/util/ipc.rs | 94 | ||||
-rw-r--r-- | components/util/lib.rs | 2 | ||||
-rw-r--r-- | components/util/linked_list.rs | 73 | ||||
-rw-r--r-- | components/util/opts.rs | 6 |
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"), |