mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-19 00:00:09 +02:00
rt: skip defer queue in block_in_place context (#7216)
This commit is contained in:
@@ -782,7 +782,13 @@ impl Context {
|
||||
}
|
||||
|
||||
pub(crate) fn defer(&self, waker: &Waker) {
|
||||
self.defer.defer(waker);
|
||||
if self.core.borrow().is_none() {
|
||||
// If there is no core, then the worker is currently in a block_in_place. In this case,
|
||||
// we cannot use the defer queue as we aren't really in the current runtime.
|
||||
waker.wake_by_ref();
|
||||
} else {
|
||||
self.defer.defer(waker);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
||||
@@ -126,6 +126,17 @@ fn unbounded_mpsc_channel() {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_in_block_in_place() {
|
||||
test_with_runtimes(|| {
|
||||
Handle::current().block_on(async {
|
||||
tokio::task::block_in_place(|| {
|
||||
Handle::current().block_on(tokio::task::yield_now());
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "wasi"))] // Wasi doesn't support file operations or bind
|
||||
rt_test! {
|
||||
use tokio::fs;
|
||||
|
||||
@@ -647,6 +647,51 @@ fn test_nested_block_in_place_with_block_on_between() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn yield_now_in_block_in_place() {
|
||||
let rt = runtime::Builder::new_multi_thread()
|
||||
.worker_threads(1)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
rt.block_on(async {
|
||||
tokio::spawn(async {
|
||||
tokio::task::block_in_place(|| {
|
||||
tokio::runtime::Handle::current().block_on(tokio::task::yield_now());
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mutex_in_block_in_place() {
|
||||
const BUDGET: usize = 128;
|
||||
|
||||
let rt = runtime::Builder::new_multi_thread()
|
||||
.worker_threads(1)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
rt.block_on(async {
|
||||
let lock = tokio::sync::Mutex::new(0);
|
||||
|
||||
tokio::spawn(async move {
|
||||
tokio::task::block_in_place(|| {
|
||||
tokio::runtime::Handle::current().block_on(async move {
|
||||
for i in 0..(BUDGET + 1) {
|
||||
let mut guard = lock.lock().await;
|
||||
*guard = i;
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
}
|
||||
|
||||
// Testing the tuning logic is tricky as it is inherently timing based, and more
|
||||
// of a heuristic than an exact behavior. This test checks that the interval
|
||||
// changes over time based on load factors. There are no assertions, completion
|
||||
|
||||
Reference in New Issue
Block a user