pedant_graph/cache/graph.rs
1//! The handle a caller holds on one cached graph.
2
3use std::sync::Arc;
4
5use crate::analysis::index::admitted_counts;
6use crate::analysis::{GraphAnalysisError, GraphAnalysisLimits, GraphEdgeSelection};
7use crate::graph::CodeGraph;
8
9use super::analysis::{CachedGraphAnalysis, DerivedState};
10use super::limits::GraphCacheLimits;
11use super::state::CacheCounters;
12use super::stats::GraphCacheStats;
13
14/// One admitted graph beside everything derived from it.
15///
16/// The derived state belongs to the graph rather than to the cache entry that
17/// retained it, so two handles on one graph share the indexes and the products
18/// either of them produced, and both keep answering after the entry is gone.
19pub(crate) struct CachedGraphState {
20 graph: Arc<CodeGraph>,
21 derived: DerivedState,
22}
23
24impl CachedGraphState {
25 /// One immutable graph, with nothing derived from it yet.
26 pub(crate) fn new(
27 graph: CodeGraph,
28 limits: GraphCacheLimits,
29 counters: Arc<CacheCounters>,
30 ) -> Self {
31 Self {
32 graph: Arc::new(graph),
33 derived: DerivedState::new(limits, counters),
34 }
35 }
36
37 /// The graph this state was built from.
38 pub(crate) fn graph(&self) -> &CodeGraph {
39 &self.graph
40 }
41
42 /// The bounded indexes and products derived from it.
43 pub(crate) fn derived(&self) -> &DerivedState {
44 &self.derived
45 }
46
47 /// What the cache that produced this graph has done so far.
48 ///
49 /// Read through the derived state, which already shares the one set of
50 /// counters this graph records against. A second handle on them here would
51 /// be a second place to keep in step with the first.
52 pub(crate) fn stats(&self) -> GraphCacheStats {
53 self.derived.counters().snapshot()
54 }
55}
56
57/// One immutable graph, shared with the cache that produced it.
58///
59/// Cloning a handle shares the graph rather than copying its records, and a
60/// handle stays valid after its cache entry is evicted, after the cache is
61/// cleared, and after the cache itself is dropped: the memory is the caller's
62/// for as long as the caller holds it.
63#[derive(Clone)]
64pub struct CachedCodeGraph {
65 state: Arc<CachedGraphState>,
66}
67
68impl CachedCodeGraph {
69 /// One handle on an admitted graph, sharing the cache's own state.
70 pub(crate) fn new(state: Arc<CachedGraphState>) -> Self {
71 Self { state }
72 }
73
74 /// The graph this handle holds.
75 pub fn graph(&self) -> &CodeGraph {
76 self.state.graph()
77 }
78
79 /// What the cache that produced this handle has done so far.
80 pub fn stats(&self) -> GraphCacheStats {
81 self.state.stats()
82 }
83
84 /// One shared analysis of this graph under `selection`, reusing the indexes
85 /// this graph already produced for it.
86 ///
87 /// The returned handle answers exactly as [`crate::GraphAnalysis`] answers
88 /// for the same graph, selection, and ceilings, whatever this graph
89 /// retained first.
90 ///
91 /// # Errors
92 ///
93 /// The same refusals [`crate::GraphAnalysis::new`] returns. The node and
94 /// selected-edge counts are proved against the caller's current ceilings
95 /// before any retained index set is examined, so a lowered ceiling refuses
96 /// exactly as it would have refused a fresh analysis.
97 pub fn analyze(
98 &self,
99 selection: GraphEdgeSelection,
100 limits: GraphAnalysisLimits,
101 ) -> Result<CachedGraphAnalysis, GraphAnalysisError> {
102 let admitted = admitted_counts(self.graph(), selection, limits)?;
103 let shared = self
104 .state
105 .derived()
106 .indexed(self.graph(), selection, admitted)?;
107 Ok(CachedGraphAnalysis::new(
108 Arc::clone(&self.state),
109 selection,
110 limits,
111 shared,
112 ))
113 }
114
115 /// Drop the selected indexes and derived products retained for this graph.
116 ///
117 /// Cumulative statistics are not reset, no analysis or product a caller
118 /// holds is invalidated, and the graph itself is untouched: the cache drops
119 /// its own strong references and nothing else.
120 pub fn clear_analysis_cache(&self) {
121 self.state.derived().clear();
122 }
123}