Skip to content

Commit 8a0832c

Browse files
authored
m: Remove the thread-local executor optimization
This was added in #37 as an optimization, but has since lead to many bugs. See the issues #53, #57 and #60 for more information. I do not have the bandwidth to address all of these bugs, so I'm taking the path of least resistance by just removing the problematic code. CLoses #53, #57 and #60 Signed-off-by: John Nunley <dev@notgull.net>
1 parent 917caad commit 8a0832c

File tree

1 file changed

+15
-152
lines changed

1 file changed

+15
-152
lines changed

Diff for: src/lib.rs

+15-152
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
2727
)]
2828

29-
use std::cell::RefCell;
3029
use std::fmt;
3130
use std::future::Future;
3231
use std::marker::PhantomData;
@@ -236,56 +235,29 @@ impl<'a> Executor<'a> {
236235
let runner = Runner::new(self.state());
237236
let mut rng = fastrand::Rng::new();
238237

239-
// Set the local queue while we're running.
240-
LocalQueue::set(self.state(), &runner.local, {
241-
let runner = &runner;
242-
async move {
243-
// A future that runs tasks forever.
244-
let run_forever = async {
245-
loop {
246-
for _ in 0..200 {
247-
let runnable = runner.runnable(&mut rng).await;
248-
runnable.run();
249-
}
250-
future::yield_now().await;
251-
}
252-
};
253-
254-
// Run `future` and `run_forever` concurrently until `future` completes.
255-
future.or(run_forever).await
238+
// A future that runs tasks forever.
239+
let run_forever = async {
240+
loop {
241+
for _ in 0..200 {
242+
let runnable = runner.runnable(&mut rng).await;
243+
runnable.run();
244+
}
245+
future::yield_now().await;
256246
}
257-
})
258-
.await
247+
};
248+
249+
// Run `future` and `run_forever` concurrently until `future` completes.
250+
future.or(run_forever).await
259251
}
260252

261253
/// Returns a function that schedules a runnable task when it gets woken up.
262254
fn schedule(&self) -> impl Fn(Runnable) + Send + Sync + 'static {
263255
let state = self.state().clone();
264256

265-
// If possible, push into the current local queue and notify the ticker.
257+
// TODO: If possible, push into the current local queue and notify the ticker.
266258
move |runnable| {
267-
let mut runnable = Some(runnable);
268-
269-
// Try to push into the local queue.
270-
LocalQueue::with(|local_queue| {
271-
// Make sure that we don't accidentally push to an executor that isn't ours.
272-
if local_queue.state != &*state as *const State as usize {
273-
return;
274-
}
275-
276-
if let Err(e) = local_queue.queue.push(runnable.take().unwrap()) {
277-
runnable = Some(e.into_inner());
278-
return;
279-
}
280-
281-
local_queue.waker.wake_by_ref();
282-
});
283-
284-
// If the local queue push failed, just push to the global queue.
285-
if let Some(runnable) = runnable {
286-
state.queue.push(runnable).unwrap();
287-
state.notify();
288-
}
259+
state.queue.push(runnable).unwrap();
260+
state.notify();
289261
}
290262
}
291263

@@ -853,106 +825,6 @@ impl Drop for Runner<'_> {
853825
}
854826
}
855827

856-
/// The state of the currently running local queue.
857-
struct LocalQueue {
858-
/// The pointer to the state of the executor.
859-
///
860-
/// Used to make sure we don't push runnables to the wrong executor.
861-
state: usize,
862-
863-
/// The concurrent queue.
864-
queue: Arc<ConcurrentQueue<Runnable>>,
865-
866-
/// The waker for the runnable.
867-
waker: Waker,
868-
}
869-
870-
impl LocalQueue {
871-
/// Run a function with the current local queue.
872-
fn with<R>(f: impl FnOnce(&LocalQueue) -> R) -> Option<R> {
873-
std::thread_local! {
874-
/// The current local queue.
875-
static LOCAL_QUEUE: RefCell<Option<LocalQueue>> = RefCell::new(None);
876-
}
877-
878-
impl LocalQueue {
879-
/// Run a function with a set local queue.
880-
async fn set<F>(
881-
state: &State,
882-
queue: &Arc<ConcurrentQueue<Runnable>>,
883-
fut: F,
884-
) -> F::Output
885-
where
886-
F: Future,
887-
{
888-
// Make the `LocalQueue` structure.
889-
let make_local_queue = |waker: &Waker| LocalQueue {
890-
state: state as *const State as usize,
891-
queue: queue.clone(),
892-
waker: waker.clone(),
893-
};
894-
895-
// Store the local queue and the current waker.
896-
let mut old = with_waker(|waker| {
897-
LOCAL_QUEUE.with(move |slot| slot.borrow_mut().replace(make_local_queue(waker)))
898-
})
899-
.await;
900-
901-
// Restore the old local queue on drop.
902-
let _guard = CallOnDrop(move || {
903-
let old = old.take();
904-
let _ = LOCAL_QUEUE.try_with(move |slot| {
905-
*slot.borrow_mut() = old;
906-
});
907-
});
908-
909-
// Pin the future.
910-
futures_lite::pin!(fut);
911-
912-
// Run it such that the waker is updated every time it's polled.
913-
future::poll_fn(move |cx| {
914-
LOCAL_QUEUE
915-
.try_with({
916-
let waker = cx.waker();
917-
move |slot| {
918-
let mut slot = slot.borrow_mut();
919-
let qaw = match slot.as_mut() {
920-
None => {
921-
// Another local queue dropped itself and replaced with None,
922-
// we can take its place!
923-
*slot = Some(make_local_queue(waker));
924-
return;
925-
}
926-
Some(qaw) => qaw,
927-
};
928-
929-
// If we've been replaced, just ignore the slot.
930-
if !Arc::ptr_eq(&qaw.queue, queue) {
931-
return;
932-
}
933-
934-
// Update the waker, if it has changed.
935-
if !qaw.waker.will_wake(waker) {
936-
qaw.waker = waker.clone();
937-
}
938-
}
939-
})
940-
.ok();
941-
942-
// Poll the future.
943-
fut.as_mut().poll(cx)
944-
})
945-
.await
946-
}
947-
}
948-
949-
LOCAL_QUEUE
950-
.try_with(|local_queue| local_queue.borrow().as_ref().map(f))
951-
.ok()
952-
.flatten()
953-
}
954-
}
955-
956828
/// Steals some items from one queue into another.
957829
fn steal<T>(src: &ConcurrentQueue<T>, dest: &ConcurrentQueue<T>) {
958830
// Half of `src`'s length rounded up.
@@ -1053,15 +925,6 @@ impl<F: FnMut()> Drop for CallOnDrop<F> {
1053925
}
1054926
}
1055927

1056-
/// Run a closure with the current waker.
1057-
fn with_waker<F: FnOnce(&Waker) -> R, R>(f: F) -> impl Future<Output = R> {
1058-
let mut f = Some(f);
1059-
future::poll_fn(move |cx| {
1060-
let f = f.take().unwrap();
1061-
Poll::Ready(f(cx.waker()))
1062-
})
1063-
}
1064-
1065928
fn _ensure_send_and_sync() {
1066929
use futures_lite::future::pending;
1067930

0 commit comments

Comments
 (0)