use core::{any::Any, cell::Cell, fmt, num::NonZero, ptr::NonNull};
use crate::{
config::Config,
ptr::Irc,
simulator::{Mark, Sim},
};
pub struct Share<C: ?Sized + Config> {
sim: Irc<Sim<C>>,
name: &'static str,
pid: Option<NonZero<usize>>,
rank: Cell<C::Rank>,
mark: Cell<Mark>,
item: NonNull<dyn Any>,
}
impl<C: ?Sized + Config> Share<C> {
pub(crate) fn root(sim: Irc<Sim<C>>) -> Self {
let default_rank = sim.config().default_rank();
Self {
sim,
name: "SimMain",
pid: None,
rank: Cell::new(default_rank),
mark: Cell::new(Mark::default()),
item: NonNull::from(&()),
}
}
pub(crate) unsafe fn new<I: Any>(
sim: Irc<Sim<C>>,
item: &I,
rank: C::Rank,
name: &'static str,
pid: NonZero<usize>,
) -> Share<C> {
Share {
sim,
name,
pid: Some(pid),
rank: Cell::new(rank),
mark: Cell::new(Mark::default()),
item: NonNull::from(item),
}
}
pub fn rank(&self) -> C::Rank {
self.rank.get()
}
pub fn name(&self) -> &'static str {
self.name
}
pub fn pid(&self) -> Option<NonZero<usize>> {
self.pid
}
pub fn item(&self) -> &dyn Any {
unsafe { self.item.as_ref() }
}
pub fn label(&self) -> Label {
Label {
name: self.name(),
pid: self.pid(),
}
}
pub(crate) fn mark(&self) -> &Cell<Mark> {
&self.mark
}
pub fn update_rank(&self, rank: C::Rank) {
self.sim
.calendar()
.update_rank(self.mark.get(), &self.rank, rank);
self.rank.set(rank);
}
pub(crate) fn sim(&self) -> &Irc<Sim<C>> {
&self.sim
}
}
impl<C: Config> fmt::Debug for Share<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Share")
.field("name", &self.name())
.field("pid", &self.pid())
.field("mark", &self.mark.get())
.field("rank", &self.rank())
.finish()
}
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct Label {
pub name: &'static str,
pub pid: Option<NonZero<usize>>,
}
impl Label {
pub fn pretty_name(&self) -> impl Iterator<Item = &'static str> {
self.name
.split_inclusive(&['<', '>', '(', ')', '[', ']', ',', ';'])
.filter_map(|part| part.rsplit(':').next())
}
}
impl fmt::Display for Label {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !f.alternate() {
for ident in self.pretty_name() {
f.write_str(ident)?;
}
} else {
f.write_str(self.name)?;
}
if let Some(pid) = self.pid {
write!(f, "#{pid}")
} else {
Ok(())
}
}
}