mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
introduce a pipeline namespace installer
This commit is contained in:
parent
47aa1ccaa2
commit
34008a317b
7 changed files with 140 additions and 7 deletions
|
@ -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"]}
|
||||
|
||||
|
|
|
@ -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!")
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate malloc_size_of;
|
||||
#[macro_use]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue