use crate::{
metadata::{identity::AssemblyIdentity, typesystem::TypeRegistry},
utils::FailFastBarrier,
Error, Result,
};
use boxcar::Vec as BoxcarVec;
use std::sync::Arc;
pub(crate) struct ProjectContext {
total_count: usize,
stage1_barrier: Arc<FailFastBarrier>,
stage2_barrier: Arc<FailFastBarrier>,
stage3_barrier: Arc<FailFastBarrier>,
stage4_barrier: Arc<FailFastBarrier>,
registries: BoxcarVec<(AssemblyIdentity, Arc<TypeRegistry>)>,
}
impl ProjectContext {
pub fn new(total_count: usize) -> Result<Self> {
Ok(Self {
total_count,
stage1_barrier: Arc::new(FailFastBarrier::new(total_count)?),
stage2_barrier: Arc::new(FailFastBarrier::new(total_count)?),
stage3_barrier: Arc::new(FailFastBarrier::new(total_count)?),
stage4_barrier: Arc::new(FailFastBarrier::new(total_count)?),
registries: BoxcarVec::new(),
})
}
pub fn wait_stage1(&self) -> Result<()> {
self.stage1_barrier
.wait()
.map_err(|e| Error::LockError(format!("Stage 1 barrier failed: {e}")))
}
pub fn wait_stage2(&self) -> Result<()> {
self.stage2_barrier
.wait()
.map_err(|e| Error::LockError(format!("Stage 2 barrier failed: {e}")))
}
pub fn wait_stage3(&self) -> Result<()> {
self.stage3_barrier
.wait()
.map_err(|e| Error::LockError(format!("Stage 3 barrier failed: {e}")))
}
pub fn wait_stage4(&self) -> Result<()> {
self.stage4_barrier
.wait()
.map_err(|e| Error::LockError(format!("Stage 4 barrier failed: {e}")))
}
pub fn register_type_registry(&self, identity: AssemblyIdentity, registry: Arc<TypeRegistry>) {
self.registries.push((identity, registry));
}
pub fn get_registries(&self) -> Vec<(AssemblyIdentity, Arc<TypeRegistry>)> {
let mut registries = Vec::new();
for (_, entry) in &self.registries {
registries.push(entry.clone());
}
registries
}
pub fn total_count(&self) -> usize {
self.total_count
}
pub fn break_all_barriers(&self, error_message: &str) {
self.stage1_barrier.break_barrier(error_message);
self.stage2_barrier.break_barrier(error_message);
self.stage3_barrier.break_barrier(error_message);
self.stage4_barrier.break_barrier(error_message);
}
pub fn register_and_wait_stage1(
&self,
identity: AssemblyIdentity,
registry: Arc<TypeRegistry>,
) -> Result<()> {
self.register_type_registry(identity, registry);
self.wait_stage1()
}
pub fn link_all_registries(&self, current_registry: &Arc<TypeRegistry>) {
for (_, (other_identity, other_registry)) in &self.registries {
if !Arc::ptr_eq(current_registry, other_registry) {
current_registry.registry_link(other_identity.clone(), other_registry.clone());
}
}
}
}