use std::{
fmt,
hash::{Hash, Hasher},
ptr,
sync::Mutex,
};
use {
dispatcher::{self, Dispatch},
subscriber::Interest,
Metadata,
};
lazy_static! {
static ref REGISTRY: Mutex<Registry> = Mutex::new(Registry {
callsites: Vec::new(),
dispatchers: Vec::new(),
});
}
struct Registry {
callsites: Vec<&'static Callsite>,
dispatchers: Vec<dispatcher::Registrar>,
}
pub trait Callsite: Sync {
fn add_interest(&self, interest: Interest);
fn clear_interest(&self);
fn metadata(&self) -> &Metadata;
}
#[derive(Clone)]
pub struct Identifier(
#[doc(hidden)]
pub &'static Callsite,
);
pub fn register(callsite: &'static Callsite) {
let mut registry = REGISTRY.lock().unwrap();
let meta = callsite.metadata();
registry.dispatchers.retain(|registrar| {
match registrar.try_register(meta) {
Some(interest) => {
callsite.add_interest(interest);
true
}
None => false,
}
});
registry.callsites.push(callsite);
}
pub(crate) fn register_dispatch(dispatch: &Dispatch) {
let mut registry = REGISTRY.lock().unwrap();
registry.dispatchers.push(dispatch.registrar());
for callsite in ®istry.callsites {
let interest = dispatch.register_callsite(callsite.metadata());
callsite.add_interest(interest);
}
}
impl PartialEq for Identifier {
fn eq(&self, other: &Identifier) -> bool {
ptr::eq(self.0, other.0)
}
}
impl Eq for Identifier {}
impl fmt::Debug for Identifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Identifier({:p})", self.0)
}
}
impl Hash for Identifier {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
(self.0 as *const Callsite).hash(state)
}
}