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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! # global-lib
//!
//! PROCESS-WIDE VALUES FOR RUST
//!
//! Set a value once and read it from anywhere in the program, edit it
//! later, or remove it: by name through a few free functions, or through a
//! typed [`Global<T>`] in a `static`. Reads are lock-free and allocate
//! nothing, so globals can sit on hot paths read by many threads at once.
//!
//! # By name
//!
//! ```
//! global_lib::set("port", 7000u16);
//! global_lib::define("app_name", "HiveDB")?; // set-once
//!
//! let port: Option<u16> = global_lib::value("port");
//! global_lib::edit::<u16>("port", |p| *p += 1)?;
//! let doubled = global_lib::with::<u16, _>("port", |p| *p * 2);
//!
//! assert!(global_lib::get::<u32>("port").is_none()); // wrong type
//! global_lib::remove("port");
//! # assert_eq!(port, Some(7000));
//! # assert_eq!(doubled, Some(14002));
//! # Ok::<(), global_lib::Error>(())
//! ```
//!
//! Any `Send + Sync + 'static` type can be stored. Asking for a different
//! type than the one stored returns `None` from [`get`], [`value`], and
//! [`with`], and an [`Error::TypeMismatch`] naming both types from
//! [`try_get`] and [`edit`].
//!
//! # Typed statics
//!
//! ```
//! use global_lib::Global;
//!
//! static MAX_CONNECTIONS: Global<usize> = Global::new();
//!
//! MAX_CONNECTIONS.set(64);
//! let n = MAX_CONNECTIONS.with(|n| *n).unwrap_or(16);
//! # assert_eq!(n, 64);
//! ```
//!
//! # Cost model
//!
//! - **Reads** publish a hazard pointer for the current snapshot, borrow
//! it, and release it: no lock, no allocation, and with [`with`] no
//! reference-count change. Readers never block writers or each other.
//! - **Writes** are serialized and copy-on-write: the map (or the single
//! value) is copied, changed, and swapped in. The old snapshot is freed
//! once no reader holds it. Globals are read far more often than written,
//! which is the trade this design makes.
//! - [`edit`] runs its closure on a copy with no lock held, then swaps
//! the copy in only if the value has not changed meanwhile, starting
//! again from the new value if it has. Concurrent edits never lose an
//! update, and the closure may use any global without risk of deadlock.
//!
//! # Global state
//!
//! The free functions use one process-wide [`Globals`] ([`globals`]),
//! created on first use. For isolated groups of values, or a fresh set per
//! test, create your own [`Globals`].
//!
//! # Secrets
//!
//! `Debug` output and errors name globals and their types, never their
//! values.
use Any;
use Arc;
pub use ;
pub use Global;
pub use ;
/// Sets the process-wide global `name` to `value`, replacing any previous
/// value of any type. See [`Globals::set`].
/// Sets the process-wide global `name` only if it is not set yet.
///
/// # Errors
///
/// [`Error::AlreadyDefined`] if it is set. See [`Globals::define`].
/// A shared handle to the process-wide global `name`, or `None` if it is
/// unset or holds another type. See [`Globals::get`].
/// A shared handle to the process-wide global `name`.
///
/// # Errors
///
/// [`Error::Missing`] or [`Error::TypeMismatch`]. See
/// [`Globals::try_get`].
/// A clone of the process-wide global `name`, or `None` if it is unset or
/// holds another type. See [`Globals::value`].
/// Runs `f` on the process-wide global `name` in place. See
/// [`Globals::with`].
/// Changes the process-wide global `name` in place.
///
/// # Errors
///
/// [`Error::Missing`] or [`Error::TypeMismatch`]. See [`Globals::edit`].
/// Removes the process-wide global `name`. Returns whether it was set.
// Called for its effect far more often than for the result.
/// Whether the process-wide global `name` is set.