1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! Authoritative graph storage with in-place writer mutation.
//!
//! Wraps `Arc<S>` in a `RwLock` so writers can call `Arc::make_mut`
//! against the live `Arc` directly. When no in-flight reader holds a
//! cloned `Arc<S>`, the live `Arc`'s strong count is 1 and `make_mut`
//! returns `&mut S` *without* cloning the graph — restoring the v0.6
//! single-writer cost for `CREATE` / `SET` / `DELETE` against large
//! graphs.
//!
//! Why not `ArcSwap`: `ArcSwap` always holds an internal `Arc<S>`, so
//! every `load_full()` produces a second strong reference. With the
//! writer mutex held, we'd still see strong count >= 2 from
//! `load_full`, forcing `Arc::make_mut` to deep-clone the graph on every
//! mutating query — that's the v0.6→v0.8 write regression. `RwLock<Arc<S>>`
//! lets the writer take exclusive access via the write guard without
//! bumping the inner refcount.
//!
//! Tradeoff: `load_full()` now goes through a brief read-lock acquire
//! (one atomic CAS in the uncontended case) instead of an `ArcSwap`
//! atomic load. For embedded use the difference is in the noise; the
//! win on the write side is many microseconds per mutating query at
//! 10k+ node graphs.
use ;
/// Authoritative graph state. Reads obtain an independent `Arc<S>`
/// snapshot; writes obtain exclusive in-place access.
pub
/// Writer's exclusive access to the live graph. Mutations happen
/// in-place via `Arc::make_mut`; on drop, the post-mutation state is
/// already live, so there's no explicit "publish" step.
pub