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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*/
//! # EBR lifecycle hooks for [`super::Store`]
//!
//! Please read this section carefully - the protocol is not difficult, but it *is* subtle.
//!
//! The transitions are a simplified version of the protocol described in [`crate::tag`]
//! that storage slots need to implement to be compatible. A state diagram is shown below:
//!
//! ```text
//! +--------------- `reclaim` ----------------+
//! | |
//! V |
//! +-----------+ +----------+
//! | Available |<---+ | Retiring |
//! +-----------+ | +----------+
//! | | ^
//! | | |
//! | `abort` `retire`
//! `acquire` | |
//! | | |
//! | +---------------+ +-----------+
//! +--->| Exclusive<'_> |---- `publish` --->| Published |
//! +---------------+ +-----------+
//! |
//! `freeze`
//! |
//! +-----------+
//! |
//! V
//! +--------+
//! | Frozen |
//! +--------+
//! ```
//!
//! ## Readable States
//!
//! * `published`: **New** references to slots may be given out in the "published" state. It is
//! possible for a transition to go from "published" to "retiring" while references are lent
//! out. This is fine as long as the lifetime of these references is bounded by a
//! [`crate::epoch::Guard`]. Using [`super::Store::guard`] will provide such a guard.
//!
//! * `frozen`: Since "frozen" is a terminal state, it is safe to give out references to
//! frozen slots.
//!
//! Note that "frozen" points differ from normal points in that they are protected from
//! being retired by the [`super::Store`]. This enables potential optimizations like
//! pre-loading and then freezing all data to be inserted, allowing safe, concurrency-free
//! read-only index builds. But for now, it mainly helps with algorithm correctness.
//!
//! ## Writable States
//!
//! * [`Exclusive`]: The exclusive stats is a little spooky. Slots can assume that an
//! [`Exclusive`] for an index `i` is exclusive for its duration. This means that
//! [`Exclusive`] implementations can lend out mutable references to its contents (for
//! example, [`super::intrusive::Exclusive::as_mut_slice`]).
//!
//! Code in [`super`] is very careful to maintain this invariant and all users of
//! [`Exclusive`] must carefully maintain this as well.
//!
//! * `reclaim`: On a call to [`Slots::reclaim`], implementations may assume exclusive access
//! to the indicated slot for the duration of the function call.
//!
//! ## Contracts
//!
//! Users of [`Slots`] must ensure that the lifecycle shown above is strictly observed.
//! Furthermore, for [`Exclusive`]s, exactly one of the terminal methods **must** be called.
//!
//! State transitions are driven by the authoritative [`super::Store`]. Before invoking a
//! transition, the store ensures the slot is not externally available in its previous
//! state. Further, the store commits the destination state only after the lifecycle API call
//! completes.
//!
//! ## Safety Considerations
//!
//! [`SlotsConfig::build`] is expected to receive two additional arguments:
//!
//! * [`epoch::RegistryHandle`]: A handle into the [`epoch::Registry`] used to protect the
//! constructed [`Slots`]. This allows implementations to check the validity of
//! [`epoch::Guard`]s via [`epoch::RegistryHandle::assert_guard_belongs`].
//!
//! Unsafe code may rely on this check and all reader construction paths should use it
//! as it is cheap.
//!
//! * [`tag::Authoritative`]: A reference to the authoritative tag source for the constructed
//! [`Slots`]. Implementations can use [`tag::Authoritative::read_only`] to obtain a
//! read-only, synchronizing view into the authoritative tag collection.
use Debug;
use crate::;
use Lifecycle;
/// A configuration for a [`Slots`].
pub
/// A lifecycle backend for [`super::Store`]'s EBR scheme.
///
/// See the [module level documentation](self) for details.
pub
/// A writable slot for [`Slots`].
///
/// [`Exclusive`]s may assume that they have exclusive ownership of their slots for their
/// duration in accordance with [`Slots::acquire`].
pub