mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
util: Add a multiprocess command-line option and implement
`OptionalIpcSender<T>`. `OptionalIpcSender<T>`dynamically switches between in-process and out-of-process communication depending on whether multiprocess mode is enabled. The multiprocess command-line switch doesn't actually turn on multiprocess mode yet, but it does control the behavior of `OptionalIpcSender<T>`.
This commit is contained in:
parent
ca9f9226b0
commit
ef9fdc6e30
5 changed files with 93 additions and 0 deletions
1
components/servo/Cargo.lock
generated
1
components/servo/Cargo.lock
generated
|
@ -1499,6 +1499,7 @@ dependencies = [
|
||||||
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cssparser 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cssparser 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
|
||||||
"lazy_static 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -25,6 +25,9 @@ git = "https://github.com/servo/rust-azure"
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
features = [ "serde-serialization" ]
|
features = [ "serde-serialization" ]
|
||||||
|
|
||||||
|
[dependencies.ipc-channel]
|
||||||
|
git = "https://github.com/pcwalton/ipc-channel"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "0.3"
|
log = "0.3"
|
||||||
bitflags = "0.3"
|
bitflags = "0.3"
|
||||||
|
|
81
components/util/ipc.rs
Normal file
81
components/util/ipc.rs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/* 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> 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ extern crate alloc;
|
||||||
#[macro_use] extern crate cssparser;
|
#[macro_use] extern crate cssparser;
|
||||||
extern crate euclid;
|
extern crate euclid;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
|
extern crate ipc_channel;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate num as num_lib;
|
extern crate num as num_lib;
|
||||||
extern crate num_cpus;
|
extern crate num_cpus;
|
||||||
|
@ -49,6 +50,7 @@ pub mod debug_utils;
|
||||||
pub mod deque;
|
pub mod deque;
|
||||||
pub mod linked_list;
|
pub mod linked_list;
|
||||||
pub mod geometry;
|
pub mod geometry;
|
||||||
|
pub mod ipc;
|
||||||
pub mod logical_geometry;
|
pub mod logical_geometry;
|
||||||
pub mod mem;
|
pub mod mem;
|
||||||
pub mod opts;
|
pub mod opts;
|
||||||
|
|
|
@ -132,6 +132,9 @@ pub struct Opts {
|
||||||
/// An optional string allowing the user agent to be set for testing.
|
/// An optional string allowing the user agent to be set for testing.
|
||||||
pub user_agent: Option<String>,
|
pub user_agent: Option<String>,
|
||||||
|
|
||||||
|
/// Whether to run in multiprocess mode.
|
||||||
|
pub multiprocess: bool,
|
||||||
|
|
||||||
/// Dumps the flow tree after a layout.
|
/// Dumps the flow tree after a layout.
|
||||||
pub dump_flow_tree: bool,
|
pub dump_flow_tree: bool,
|
||||||
|
|
||||||
|
@ -251,6 +254,7 @@ pub fn default_opts() -> Opts {
|
||||||
webdriver_port: None,
|
webdriver_port: None,
|
||||||
initial_window_size: Size2D::typed(800, 600),
|
initial_window_size: Size2D::typed(800, 600),
|
||||||
user_agent: None,
|
user_agent: None,
|
||||||
|
multiprocess: false,
|
||||||
dump_flow_tree: false,
|
dump_flow_tree: false,
|
||||||
dump_display_list: false,
|
dump_display_list: false,
|
||||||
dump_display_list_json: 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::optflagopt("", "webdriver", "Start remote WebDriver server on port", "7000"),
|
||||||
getopts::optopt("", "resolution", "Set window resolution.", "800x600"),
|
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::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",
|
getopts::optopt("Z", "debug",
|
||||||
"A comma-separated string of debug options. Pass help to show available options.", ""),
|
"A comma-separated string of debug options. Pass help to show available options.", ""),
|
||||||
getopts::optflag("h", "help", "Print this message"),
|
getopts::optflag("h", "help", "Print this message"),
|
||||||
|
@ -421,6 +426,7 @@ pub fn from_cmdline_args(args: &[String]) {
|
||||||
webdriver_port: webdriver_port,
|
webdriver_port: webdriver_port,
|
||||||
initial_window_size: initial_window_size,
|
initial_window_size: initial_window_size,
|
||||||
user_agent: opt_match.opt_str("u"),
|
user_agent: opt_match.opt_str("u"),
|
||||||
|
multiprocess: opt_match.opt_present("M"),
|
||||||
show_debug_borders: debug_options.contains(&"show-compositor-borders"),
|
show_debug_borders: debug_options.contains(&"show-compositor-borders"),
|
||||||
show_debug_fragment_borders: debug_options.contains(&"show-fragment-borders"),
|
show_debug_fragment_borders: debug_options.contains(&"show-fragment-borders"),
|
||||||
show_debug_parallel_paint: debug_options.contains(&"show-parallel-paint"),
|
show_debug_parallel_paint: debug_options.contains(&"show-parallel-paint"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue