fuchsia_inspect_contrib/graph/
edge.rs1use super::types::VertexId;
6use super::{Vertex, VertexMetadata};
7use fuchsia_inspect as inspect;
8use fuchsia_sync::RwLock;
9use std::sync::atomic::{AtomicU64, Ordering};
10use std::sync::{Arc, Weak};
11
12#[derive(Debug)]
14pub struct Edge<EM> {
15 state: Arc<RwLock<EdgeState<EM>>>,
16 id: u64,
17}
18
19static NEXT_ID: AtomicU64 = AtomicU64::new(0);
20
21pub trait EdgeMetadata {}
22
23impl<EM> Edge<EM> {
24 pub(crate) fn new<VM>(
25 from: &Vertex<VM>,
26 to: &mut Vertex<VM>,
27 init_metadata: impl FnOnce(inspect::Node) -> EM,
28 ) -> Self
29 where
30 VM: VertexMetadata<EdgeMeta = EM>,
31 {
32 let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
33 let to_id = to.id().get_id();
34 let (node, metadata) = from.outgoing_edges_node.atomic_update(|parent| {
35 let node = parent.create_child(to_id.as_ref());
36 node.record_uint("edge_id", id);
37 let metadata = init_metadata(node.create_child("meta"));
38 (node, metadata)
39 });
40 let state = Arc::new(RwLock::new(EdgeState::Active { metadata, _node: node }));
41 Self { state, id }
42 }
43
44 pub fn maybe_update_meta(&self, cb: impl FnOnce(&mut EM)) {
45 let mut lock = self.state.write();
46 if let Some(meta) = lock.metadata_mut() {
47 cb(meta);
48 }
49 }
50
51 pub fn id(&self) -> u64 {
52 self.id
53 }
54
55 pub(crate) fn weak_ref(&self) -> WeakEdgeRef<EM> {
56 WeakEdgeRef(Arc::downgrade(&self.state))
57 }
58}
59
60#[derive(Debug)]
61enum EdgeState<EM> {
62 Active { metadata: EM, _node: inspect::Node },
63 Gone,
64}
65
66impl<EM> EdgeState<EM> {
67 pub fn mark_as_gone(&mut self) {
68 match self {
69 Self::Active { .. } => *self = Self::Gone,
70 Self::Gone { .. } => {}
71 }
72 }
73
74 fn metadata_mut(&mut self) -> Option<&mut EM> {
75 match self {
76 EdgeState::Active { metadata, .. } => Some(metadata),
77 EdgeState::Gone => None,
78 }
79 }
80}
81
82#[derive(Debug)]
83pub(crate) struct WeakEdgeRef<EM>(Weak<RwLock<EdgeState<EM>>>);
84
85impl<EM> Clone for WeakEdgeRef<EM> {
86 fn clone(&self) -> Self {
87 Self(self.0.clone())
88 }
89}
90
91impl<EM> WeakEdgeRef<EM> {
92 pub fn mark_as_gone(&self) {
93 if let Some(value) = self.0.upgrade() {
94 value.write().mark_as_gone();
95 }
96 }
97
98 pub fn is_valid(&self) -> bool {
99 self.0.upgrade().map(|v| matches!(*v.read(), EdgeState::Active { .. })).unwrap_or(false)
100 }
101}