1
+ use crate :: task:: local_waker_ref_from_nonlocal;
1
2
use futures_core:: future:: Future ;
2
3
use futures_core:: task:: { LocalWaker , Poll , Wake , Waker } ;
3
4
use slab:: Slab ;
4
- use std:: fmt;
5
5
use std:: cell:: UnsafeCell ;
6
+ use std:: fmt;
6
7
use std:: marker:: Unpin ;
7
8
use std:: pin:: Pin ;
8
- use std:: sync:: { Arc , Mutex } ;
9
9
use std:: sync:: atomic:: AtomicUsize ;
10
10
use std:: sync:: atomic:: Ordering :: SeqCst ;
11
- use std:: task :: local_waker_from_nonlocal ;
11
+ use std:: sync :: { Arc , Mutex } ;
12
12
13
13
/// A future that is cloneable and can be polled in multiple threads.
14
- /// Use [`FutureExt::shared()`](crate::FutureExt::shared) method to convert any future into a `Shared` future.
14
+ /// Use the [`shared`](crate::FutureExt::shared) combinator method to convert
15
+ /// any future into a `Shared` future.
15
16
#[ must_use = "futures do nothing unless polled" ]
16
17
pub struct Shared < Fut : Future > {
17
18
inner : Option < Arc < Inner < Fut > > > ,
@@ -43,8 +44,7 @@ impl<Fut: Future> fmt::Debug for Shared<Fut> {
43
44
44
45
impl < Fut : Future > fmt:: Debug for Inner < Fut > {
45
46
fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
46
- fmt. debug_struct ( "Inner" )
47
- . finish ( )
47
+ fmt. debug_struct ( "Inner" ) . finish ( )
48
48
}
49
49
}
50
50
@@ -75,14 +75,16 @@ const NULL_WAKER_KEY: usize = usize::max_value();
75
75
76
76
impl < Fut : Future > Shared < Fut > {
77
77
pub ( super ) fn new ( future : Fut ) -> Shared < Fut > {
78
+ let inner = Inner {
79
+ future_or_output : UnsafeCell :: new ( FutureOrOutput :: Future ( future) ) ,
80
+ notifier : Arc :: new ( Notifier {
81
+ state : AtomicUsize :: new ( IDLE ) ,
82
+ wakers : Mutex :: new ( Some ( Slab :: new ( ) ) ) ,
83
+ } ) ,
84
+ } ;
85
+
78
86
Shared {
79
- inner : Some ( Arc :: new ( Inner {
80
- future_or_output : UnsafeCell :: new ( FutureOrOutput :: Future ( future) ) ,
81
- notifier : Arc :: new ( Notifier {
82
- state : AtomicUsize :: new ( IDLE ) ,
83
- wakers : Mutex :: new ( Some ( Slab :: new ( ) ) ) ,
84
- } ) ,
85
- } ) ) ,
87
+ inner : Some ( Arc :: new ( inner) ) ,
86
88
waker_key : NULL_WAKER_KEY ,
87
89
}
88
90
}
@@ -93,36 +95,37 @@ where
93
95
Fut : Future ,
94
96
Fut :: Output : Clone ,
95
97
{
96
- /// Returns Some containing a reference to this [`Shared`](crate::future::Shared)'s output if it has
97
- /// already been computed by a clone or [`None`](std::option::Option::None) if it hasn't been computed yet
98
- /// or if this [`Shared`](std::option::Option::Some) already returned its output from poll.
98
+ /// Returns [`Some`] containing a reference to this [`Shared`]'s output if
99
+ /// it has already been computed by a clone or [`None`] if it hasn't been
100
+ /// computed yet or this [`Shared`] already returned its output from
101
+ /// [`poll`](Future::poll).
99
102
pub fn peek ( & self ) -> Option < & Fut :: Output > {
100
- match self . inner . as_ref ( ) . map ( |inner| inner. notifier . state . load ( SeqCst ) ) {
101
- Some ( COMPLETE ) => unsafe { Some ( self . inner ( ) . get_output ( ) ) } ,
102
- Some ( POISONED ) => panic ! ( "inner future panicked during poll" ) ,
103
- _ => None ,
103
+ if let Some ( inner) = self . inner . as_ref ( ) {
104
+ match inner. notifier . state . load ( SeqCst ) {
105
+ COMPLETE => unsafe { return Some ( inner. output ( ) ) } ,
106
+ POISONED => panic ! ( "inner future panicked during poll" ) ,
107
+ _ => { }
108
+ }
104
109
}
105
- }
106
-
107
- fn inner ( & self ) -> & Arc < Inner < Fut > > {
108
- Self :: inner_ ( & self . inner )
109
- }
110
-
111
- fn inner_ ( inner : & Option < Arc < Inner < Fut > > > ) -> & Arc < Inner < Fut > > {
112
- inner. as_ref ( ) . expect ( "Shared future polled again after completion" )
110
+ None
113
111
}
114
112
115
113
/// Registers the current task to receive a wakeup when `Inner` is awoken.
116
114
fn set_waker ( & mut self , lw : & LocalWaker ) {
117
115
// Acquire the lock first before checking COMPLETE to ensure there
118
116
// isn't a race.
119
- let mut wakers = Self :: inner_ ( & self . inner ) . notifier . wakers . lock ( ) . unwrap ( ) ;
120
- let wakers = if let Some ( wakers) = wakers. as_mut ( ) {
117
+ let mut wakers_guard = if let Some ( inner) = self . inner . as_ref ( ) {
118
+ inner. notifier . wakers . lock ( ) . unwrap ( )
119
+ } else {
120
+ return ;
121
+ } ;
122
+
123
+ let wakers = if let Some ( wakers) = wakers_guard. as_mut ( ) {
121
124
wakers
122
125
} else {
123
- // The value is already available, so there's no need to set the waker.
124
- return
126
+ return ;
125
127
} ;
128
+
126
129
if self . waker_key == NULL_WAKER_KEY {
127
130
self . waker_key = wakers. insert ( Some ( lw. clone ( ) . into_waker ( ) ) ) ;
128
131
} else {
@@ -143,29 +146,27 @@ where
143
146
144
147
/// Safety: callers must first ensure that `self.inner.state`
145
148
/// is `COMPLETE`
146
- unsafe fn take_or_clone_output ( inner : Arc < Inner < Fut > > ) -> Fut :: Output {
149
+ unsafe fn take_or_clone_output ( & mut self ) -> Fut :: Output {
150
+ let inner = self . inner . take ( ) . unwrap ( ) ;
151
+
147
152
match Arc :: try_unwrap ( inner) {
148
- Ok ( inner) => {
149
- match inner. future_or_output . into_inner ( ) {
150
- FutureOrOutput :: Output ( item) => item,
151
- FutureOrOutput :: Future ( _) => unreachable ! ( ) ,
152
- }
153
- }
154
- Err ( inner) => inner. get_output ( ) . clone ( ) ,
153
+ Ok ( inner) => match inner. future_or_output . into_inner ( ) {
154
+ FutureOrOutput :: Output ( item) => item,
155
+ FutureOrOutput :: Future ( _) => unreachable ! ( ) ,
156
+ } ,
157
+ Err ( inner) => inner. output ( ) . clone ( ) ,
155
158
}
156
159
}
157
-
158
160
}
159
161
160
-
161
162
impl < Fut > Inner < Fut >
162
163
where
163
164
Fut : Future ,
164
165
Fut :: Output : Clone ,
165
166
{
166
167
/// Safety: callers must first ensure that `self.inner.state`
167
168
/// is `COMPLETE`
168
- unsafe fn get_output ( & self ) -> & Fut :: Output {
169
+ unsafe fn output ( & self ) -> & Fut :: Output {
169
170
match & * self . future_or_output . get ( ) {
170
171
FutureOrOutput :: Output ( ref item) => & item,
171
172
FutureOrOutput :: Future ( _) => unreachable ! ( ) ,
@@ -182,30 +183,33 @@ where
182
183
fn poll ( mut self : Pin < & mut Self > , lw : & LocalWaker ) -> Poll < Self :: Output > {
183
184
let this = & mut * self ;
184
185
185
- // Assert that we aren't completed
186
- this. inner ( ) ;
187
-
188
186
this. set_waker ( lw) ;
189
187
190
- match this. inner ( ) . notifier . state . compare_and_swap ( IDLE , POLLING , SeqCst ) {
188
+ let inner = if let Some ( inner) = this. inner . as_ref ( ) {
189
+ inner
190
+ } else {
191
+ panic ! ( "Shared future polled again after completion" ) ;
192
+ } ;
193
+
194
+ match inner. notifier . state . compare_and_swap ( IDLE , POLLING , SeqCst ) {
191
195
IDLE => {
192
196
// Lock acquired, fall through
193
197
}
194
198
POLLING | REPOLL => {
195
199
// Another task is currently polling, at this point we just want
196
- // to ensure that our task handle is currently registered
200
+ // to ensure that the waker for this task is registered
197
201
198
202
return Poll :: Pending ;
199
203
}
200
204
COMPLETE => {
201
- let inner = self . inner . take ( ) . unwrap ( ) ;
202
- return unsafe { Poll :: Ready ( Self :: take_or_clone_output ( inner ) ) } ;
205
+ // Safety: We're in the COMPLETE state
206
+ return unsafe { Poll :: Ready ( this . take_or_clone_output ( ) ) } ;
203
207
}
204
208
POISONED => panic ! ( "inner future panicked during poll" ) ,
205
209
_ => unreachable ! ( ) ,
206
210
}
207
211
208
- let waker = local_waker_from_nonlocal ( this . inner ( ) . notifier . clone ( ) ) ;
212
+ let waker = local_waker_ref_from_nonlocal ( & inner. notifier ) ;
209
213
let lw = & waker;
210
214
211
215
struct Reset < ' a > ( & ' a AtomicUsize ) ;
@@ -220,36 +224,29 @@ where
220
224
}
221
225
}
222
226
227
+ let _reset = Reset ( & inner. notifier . state ) ;
223
228
224
229
let output = loop {
225
- let inner = this. inner ( ) ;
226
- let _reset = Reset ( & inner. notifier . state ) ;
227
-
228
- // Poll the future
229
- let res = unsafe {
230
- if let FutureOrOutput :: Future ( future) =
231
- & mut * inner. future_or_output . get ( )
232
- {
233
- Pin :: new_unchecked ( future) . poll ( lw)
234
- } else {
235
- unreachable ! ( )
230
+ let future = unsafe {
231
+ match & mut * inner. future_or_output . get ( ) {
232
+ FutureOrOutput :: Future ( fut) => Pin :: new_unchecked ( fut) ,
233
+ _ => unreachable ! ( ) ,
236
234
}
237
235
} ;
238
- match res {
236
+
237
+ let poll = future. poll ( & lw) ;
238
+
239
+ match poll {
239
240
Poll :: Pending => {
240
- // Not ready, try to release the handle
241
- match inner
242
- . notifier
243
- . state
244
- . compare_and_swap ( POLLING , IDLE , SeqCst )
245
- {
241
+ let state = & inner. notifier . state ;
242
+ match state. compare_and_swap ( POLLING , IDLE , SeqCst ) {
246
243
POLLING => {
247
244
// Success
248
245
return Poll :: Pending ;
249
246
}
250
247
REPOLL => {
251
- // Gotta poll again!
252
- let prev = inner . notifier . state . swap ( POLLING , SeqCst ) ;
248
+ // Was woken since: Gotta poll again!
249
+ let prev = state. swap ( POLLING , SeqCst ) ;
253
250
assert_eq ! ( prev, REPOLL ) ;
254
251
}
255
252
_ => unreachable ! ( ) ,
@@ -259,31 +256,27 @@ where
259
256
}
260
257
} ;
261
258
262
- if Arc :: get_mut ( this. inner . as_mut ( ) . unwrap ( ) ) . is_some ( ) {
263
- this. inner . take ( ) ;
264
- return Poll :: Ready ( output) ;
265
- }
266
-
267
- let inner = this. inner ( ) ;
268
-
269
- let _reset = Reset ( & inner. notifier . state ) ;
270
-
271
259
unsafe {
272
260
* inner. future_or_output . get ( ) =
273
- FutureOrOutput :: Output ( output. clone ( ) ) ;
261
+ FutureOrOutput :: Output ( output) ;
274
262
}
275
263
276
- // Complete the future
277
- let mut lock = inner. notifier . wakers . lock ( ) . unwrap ( ) ;
278
264
inner. notifier . state . store ( COMPLETE , SeqCst ) ;
279
- let wakers = & mut lock. take ( ) . unwrap ( ) ;
265
+
266
+ // Wake all tasks and drop the slab
267
+ let mut wakers_guard = inner. notifier . wakers . lock ( ) . unwrap ( ) ;
268
+ let wakers = & mut wakers_guard. take ( ) . unwrap ( ) ;
280
269
for ( _key, opt_waker) in wakers {
281
270
if let Some ( waker) = opt_waker. take ( ) {
282
271
waker. wake ( ) ;
283
272
}
284
273
}
285
274
286
- Poll :: Ready ( output)
275
+ drop ( _reset) ; // Make borrow checker happy
276
+ drop ( wakers_guard) ;
277
+
278
+ // Safety: We're in the COMPLETE state
279
+ unsafe { Poll :: Ready ( this. take_or_clone_output ( ) ) }
287
280
}
288
281
}
289
282
0 commit comments