Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 46f0fb1

Browse files
author
Stjepan Glavina
authored
Make sure each invocation of block_on uses its own Parker (#358)
1 parent e405544 commit 46f0fb1

File tree

2 files changed

+25
-12
lines changed

2 files changed

+25
-12
lines changed

‎Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ async-task = "1.0.0"
3030
cfg-if = "0.1.9"
3131
crossbeam-channel = "0.3.9"
3232
crossbeam-deque = "0.7.1"
33+
crossbeam-utils = "0.6.6"
3334
futures-core-preview = "=0.3.0-alpha.19"
3435
futures-io-preview = "=0.3.0-alpha.19"
3536
futures-timer = "1.0.2"

‎src/task/block_on.rs‎

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use std::cell::UnsafeCell;
1+
use std::cell::{Cell,UnsafeCell};
22
use std::mem::{self, ManuallyDrop};
33
use std::panic::{self, AssertUnwindSafe, UnwindSafe};
44
use std::pin::Pin;
55
use std::sync::Arc;
66
use std::task::{RawWaker, RawWakerVTable};
7-
use std::thread::{self, Thread};
7+
use std::thread;
8+
9+
use crossbeam_utils::sync::Parker;
810

911
use super::task;
1012
use super::task_local;
@@ -119,46 +121,56 @@ where
119121
F: Future<Output = T>,
120122
{
121123
thread_local! {
122-
static ARC_THREAD: Arc<Thread> = Arc::new(thread::current());
124+
// May hold a pre-allocated parker that can be reused for efficiency.
125+
//
126+
// Note that each invocation of `block` needs its own parker. In particular, if `block`
127+
// recursively calls itself, we must make sure that each recursive call uses a distinct
128+
// parker instance.
129+
static CACHE: Cell<Option<Arc<Parker>>> = Cell::new(None);
123130
}
124131

125132
pin_utils::pin_mut!(f);
126133

127-
ARC_THREAD.with(|arc_thread: &Arc<Thread>| {
128-
let ptr = (&**arc_thread as *const Thread) as *const ();
134+
CACHE.with(|cache| {
135+
// Reuse a cached parker or create a new one for this invocation of `block`.
136+
let arc_parker: Arc<Parker> = cache.take().unwrap_or_else(|| Arc::new(Parker::new()));
137+
138+
let ptr = (&*arc_parker as *const Parker) as *const ();
129139
let vt = vtable();
130140

131141
let waker = unsafe { ManuallyDrop::new(Waker::from_raw(RawWaker::new(ptr, vt))) };
132142
let cx = &mut Context::from_waker(&waker);
133143

134144
loop {
135145
if let Poll::Ready(t) = f.as_mut().poll(cx) {
146+
// Save the parker for the next invocation of `block`.
147+
cache.set(Some(arc_parker));
136148
return t;
137149
}
138-
thread::park();
150+
arc_parker.park();
139151
}
140152
})
141153
}
142154

143155
fn vtable() -> &'static RawWakerVTable {
144156
unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
145-
let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Thread));
157+
let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Parker));
146158
mem::forget(arc.clone());
147159
RawWaker::new(ptr, vtable())
148160
}
149161

150162
unsafe fn wake_raw(ptr: *const ()) {
151-
let arc = Arc::from_raw(ptr as *const Thread);
152-
arc.unpark();
163+
let arc = Arc::from_raw(ptr as *const Parker);
164+
arc.unparker().unpark();
153165
}
154166

155167
unsafe fn wake_by_ref_raw(ptr: *const ()) {
156-
let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Thread));
157-
arc.unpark();
168+
let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Parker));
169+
arc.unparker().unpark();
158170
}
159171

160172
unsafe fn drop_raw(ptr: *const ()) {
161-
drop(Arc::from_raw(ptr as *const Thread))
173+
drop(Arc::from_raw(ptr as *const Parker))
162174
}
163175

164176
&RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /