use std::sync::Arc;
use crate::handle::NodeId;
#[derive(Debug, Clone)]
pub enum TopologyEvent {
NodeRegistered(NodeId),
NodeTornDown(NodeId),
DepsChanged {
node: NodeId,
old_deps: Vec<NodeId>,
new_deps: Vec<NodeId>,
},
}
pub type TopologySink = Arc<dyn Fn(&TopologyEvent) + Send + Sync>;
#[must_use = "TopologySubscription holds the subscription; dropping it unregisters the sink"]
pub struct TopologySubscription {
id: u64,
state: std::sync::Weak<parking_lot::Mutex<super::node::CoreState>>,
}
impl Drop for TopologySubscription {
fn drop(&mut self) {
if let Some(state) = self.state.upgrade() {
let mut s = state.lock();
s.topology_sinks.remove(&self.id);
}
}
}
const _: fn() = || {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<TopologySubscription>();
};
impl super::node::Core {
pub fn subscribe_topology(&self, sink: TopologySink) -> TopologySubscription {
let mut s = self.lock_state();
let id = s.next_topology_id;
s.next_topology_id += 1;
s.topology_sinks.insert(id, sink);
TopologySubscription {
id,
state: Arc::downgrade(&self.state),
}
}
pub(crate) fn fire_topology_event(&self, event: &TopologyEvent) {
let sinks: Vec<TopologySink> = {
let s = self.state.lock();
s.topology_sinks.values().cloned().collect()
};
for sink in sinks {
sink(event);
}
}
}