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
use atomic;
use unlikely;
use crateAtomic;
/// an epoch id. valid epoch id values are all even integers greater than 0 (2,4,6,8,...).
///
/// the reason for these constraints is to allow for memory-efficient encoding of the thread state.
///
/// the fact that all epoch ids are even allows us to encode information in the least significant bit.
/// and, the fact that the epoch id is non-zero allows us to encode an empty thread state value as just a 0 value.
pub type EpochId = cfg_select! ;
/// the minimum valid epoch id value.
pub const EPOCH_ID_MIN: EpochId = 2;
/// the maximum practical value the epoch id will ever have.
/// the epoch id grows in increments of 2 and starts at a value of 2, so it is always even.
/// thus, its max value is not the underlying integer type's max value, instead it is 1 less.
pub const EPOCH_ID_MAX: EpochId = MAX - 1;
/// the current global epoch id.
/// its value must always be a valid epoch id value.
///
/// used to synchronize threads that are waiting for a grace period with all other threads, by making all threads constantly load this
/// value and publish their last seen epoch id.
/// a waiter can then increment it and wait until all threads see his increment in their last seen epoch id value.
static CUR_EPOCH_ID: = new;
/// an error returned when an overflow is detected while trying to increment the epoch id.
/// loads the current epoch id atomically with the given ordering. this only performs a single atomic load operation.
/// increments the epoch id atomically, returning the new epoch id after the increment.
///
/// if the epoch id would overflow due to the increment, this function returns an error, and the epoch id is guaranteed to be set to its
/// max value until reset.
///
/// in case this function succeeds, the increment has release ordering, guaranteeing that the swap of the rcu protected pointer happens
/// before the increment of the epoch id whenever the epoch id is loaded with acquire ordering when the threads pass through a quiescent
/// state.
///
/// in the failure case, the increment may or many not happen, and if it does, it happens with release ordering.
/// directly sets the epoch id to the given value with the given ordering.