aboutsummaryrefslogtreecommitdiffstats
path: root/components/msg
diff options
context:
space:
mode:
Diffstat (limited to 'components/msg')
-rw-r--r--components/msg/Cargo.toml3
-rw-r--r--components/msg/constellation_msg.rs82
-rw-r--r--components/msg/lib.rs2
3 files changed, 87 insertions, 0 deletions
diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml
index 5d8747bdfcf..0b5763ab641 100644
--- a/components/msg/Cargo.toml
+++ b/components/msg/Cargo.toml
@@ -13,8 +13,11 @@ test = false
doctest = false
[dependencies]
+lazy_static = "1"
+ipc-channel = "0.11"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = "0.1"
+parking_lot = "0.8"
serde = "1.0.60"
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs
index b8ba3c84e31..94370a56e2c 100644
--- a/components/msg/constellation_msg.rs
+++ b/components/msg/constellation_msg.rs
@@ -5,10 +5,13 @@
//! The high-level interface from script to constellation. Using this abstract interface helps
//! reduce coupling between these two components.
+use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
+use parking_lot::Mutex;
use std::cell::Cell;
use std::fmt;
use std::mem;
use std::num::NonZeroU32;
+use std::sync::Arc;
use std::time::Duration;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
@@ -17,12 +20,71 @@ pub enum TraversalDirection {
Back(usize),
}
+#[derive(Debug, Deserialize, Serialize)]
+/// Request a pipeline-namespace id from the constellation.
+pub struct PipelineNamespaceRequest(pub IpcSender<PipelineNamespaceId>);
+
+/// A per-process installer of pipeline-namespaces.
+pub struct PipelineNamespaceInstaller {
+ request_sender: Option<IpcSender<PipelineNamespaceRequest>>,
+ namespace_sender: IpcSender<PipelineNamespaceId>,
+ namespace_receiver: IpcReceiver<PipelineNamespaceId>,
+}
+
+impl PipelineNamespaceInstaller {
+ pub fn new() -> Self {
+ let (namespace_sender, namespace_receiver) =
+ ipc::channel().expect("PipelineNamespaceInstaller ipc channel failure");
+ PipelineNamespaceInstaller {
+ request_sender: None,
+ namespace_sender: namespace_sender,
+ namespace_receiver: namespace_receiver,
+ }
+ }
+
+ /// Provide a request sender to send requests to the constellation.
+ pub fn set_sender(&mut self, sender: IpcSender<PipelineNamespaceRequest>) {
+ self.request_sender = Some(sender);
+ }
+
+ /// Install a namespace, requesting a new Id from the constellation.
+ pub fn install_namespace(&self) {
+ match self.request_sender.as_ref() {
+ Some(sender) => {
+ let _ = sender.send(PipelineNamespaceRequest(self.namespace_sender.clone()));
+ let namespace_id = self
+ .namespace_receiver
+ .recv()
+ .expect("The constellation to make a pipeline namespace id available");
+ PipelineNamespace::install(namespace_id);
+ },
+ None => unreachable!("PipelineNamespaceInstaller should have a request_sender setup"),
+ }
+ }
+}
+
+lazy_static! {
+ /// A per-process unique pipeline-namespace-installer.
+ /// Accessible via PipelineNamespace.
+ ///
+ /// Use PipelineNamespace::set_installer_sender to initiate with a sender to the constellation,
+ /// when a new process has been created.
+ ///
+ /// Use PipelineNamespace::fetch_install to install a unique pipeline-namespace from the calling thread.
+ static ref PIPELINE_NAMESPACE_INSTALLER: Arc<Mutex<PipelineNamespaceInstaller>> =
+ Arc::new(Mutex::new(PipelineNamespaceInstaller::new()));
+}
+
/// Each pipeline ID needs to be unique. However, it also needs to be possible to
/// generate the pipeline ID from an iframe element (this simplifies a lot of other
/// code that makes use of pipeline IDs).
///
/// To achieve this, each pipeline index belongs to a particular namespace. There is
/// a namespace for the constellation thread, and also one for every script thread.
+///
+/// A namespace can be installed for any other thread in a process
+/// where an pipeline-installer has been initialized.
+///
/// This allows pipeline IDs to be generated by any of those threads without conflicting
/// with pipeline IDs created by other script threads or the constellation. The
/// constellation is the only code that is responsible for creating new *namespaces*.
@@ -39,6 +101,7 @@ pub struct PipelineNamespace {
}
impl PipelineNamespace {
+ /// Install a namespace for a given Id.
pub fn install(namespace_id: PipelineNamespaceId) {
PIPELINE_NAMESPACE.with(|tls| {
assert!(tls.get().is_none());
@@ -49,6 +112,25 @@ impl PipelineNamespace {
});
}
+ /// Setup the pipeline-namespace-installer, by providing it with a sender to the constellation.
+ /// Idempotent in single-process mode.
+ pub fn set_installer_sender(sender: IpcSender<PipelineNamespaceRequest>) {
+ PIPELINE_NAMESPACE_INSTALLER.lock().set_sender(sender);
+ }
+
+ /// Install a namespace in the current thread, without requiring having a namespace Id ready.
+ /// Panics if called more than once per thread.
+ pub fn auto_install() {
+ // Note that holding the lock for the duration of the call is irrelevant to performance,
+ // since a thread would have to block on the ipc-response from the constellation,
+ // with the constellation already acting as a global lock on namespace ids,
+ // and only being able to handle one request at a time.
+ //
+ // Hence, any other thread attempting to concurrently install a namespace
+ // would have to wait for the current call to finish, regardless of the lock held here.
+ PIPELINE_NAMESPACE_INSTALLER.lock().install_namespace();
+ }
+
fn next_index(&mut self) -> NonZeroU32 {
self.index += 1;
NonZeroU32::new(self.index).expect("pipeline id index wrapped!")
diff --git a/components/msg/lib.rs b/components/msg/lib.rs
index 6b5afe9ea13..4fe53230c46 100644
--- a/components/msg/lib.rs
+++ b/components/msg/lib.rs
@@ -5,6 +5,8 @@
#![deny(unsafe_code)]
#[macro_use]
+extern crate lazy_static;
+#[macro_use]
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;