1
1
use crate :: task:: Waker ;
2
2
3
+ use crossbeam_utils:: Backoff ;
3
4
use std:: num:: NonZeroUsize ;
5
+ use std:: ops:: { Deref , DerefMut } ;
6
+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
4
7
5
8
struct WakerNode {
6
9
/// Previous `WakerNode` in the queue. If this node is the first node, it shall point to the last node.
@@ -19,6 +22,7 @@ unsafe impl Sync for WakerList {}
19
22
20
23
impl WakerList {
21
24
/// Create a new empty `WakerList`
25
+ #[ inline]
22
26
pub fn new ( ) -> Self {
23
27
Self {
24
28
head : std:: ptr:: null_mut ( ) ,
@@ -128,3 +132,67 @@ impl<'a> Iterator for Iter<'a> {
128
132
Some ( unsafe { & mut ( * ptr) . waker } )
129
133
}
130
134
}
135
+
136
+ /// This is identical to a Spinlock<WakerList>, but is efficient in space and occupies the same
137
+ /// amount of memory as a pointer. Performance-wise it can be better than a spinlock because once
138
+ /// the lock is acquired, modification to the WakerList is on the stack, and thus is not on the
139
+ /// same cache line as the atomic variable itself, relieving some contention.
140
+ pub struct WakerListLock {
141
+ /// If this value is 1, it represents that it is locked.
142
+ /// All other values represent a valid `*mut WakerNode`.
143
+ value : AtomicUsize ,
144
+ }
145
+
146
+ impl WakerListLock {
147
+ /// Returns a new pointer lock initialized with `value`.
148
+ #[ inline]
149
+ pub fn new ( value : WakerList ) -> Self {
150
+ Self {
151
+ value : AtomicUsize :: new ( value. head as usize ) ,
152
+ }
153
+ }
154
+
155
+ /// Locks the `WakerListLock`.
156
+ pub fn lock ( & self ) -> WakerListLockGuard < ' _ > {
157
+ let backoff = Backoff :: new ( ) ;
158
+ loop {
159
+ let value = self . value . swap ( 1 , Ordering :: Acquire ) ;
160
+ if value != 1 {
161
+ return WakerListLockGuard {
162
+ parent : self ,
163
+ list : WakerList {
164
+ head : value as * mut WakerNode ,
165
+ } ,
166
+ } ;
167
+ }
168
+ backoff. snooze ( ) ;
169
+ }
170
+ }
171
+ }
172
+
173
+ pub struct WakerListLockGuard < ' a > {
174
+ parent : & ' a WakerListLock ,
175
+ list : WakerList ,
176
+ }
177
+
178
+ impl < ' a > Drop for WakerListLockGuard < ' a > {
179
+ fn drop ( & mut self ) {
180
+ self . parent
181
+ . value
182
+ . store ( self . list . head as usize , Ordering :: Release ) ;
183
+ }
184
+ }
185
+
186
+ impl < ' a > Deref for WakerListLockGuard < ' a > {
187
+ type Target = WakerList ;
188
+
189
+ fn deref ( & self ) -> & WakerList {
190
+ & self . list
191
+ }
192
+ }
193
+
194
+ impl < ' a > DerefMut for WakerListLockGuard < ' a > {
195
+ fn deref_mut ( & mut self ) -> & mut WakerList {
196
+ & mut self . list
197
+ }
198
+ }
0 commit comments