aboutsummaryrefslogtreecommitdiff
path: root/src/task/local.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/task/local.rs')
-rw-r--r--src/task/local.rs47
1 files changed, 14 insertions, 33 deletions
diff --git a/src/task/local.rs b/src/task/local.rs
index e4a198b..0675faa 100644
--- a/src/task/local.rs
+++ b/src/task/local.rs
@@ -1,8 +1,8 @@
//! Runs `!Send` futures on the current thread.
use crate::loom::cell::UnsafeCell;
use crate::loom::sync::{Arc, Mutex};
-use crate::loom::thread::{self, ThreadId};
use crate::runtime::task::{self, JoinHandle, LocalOwnedTasks, Task};
+use crate::runtime::{context, ThreadId};
use crate::sync::AtomicWaker;
use crate::util::RcCell;
@@ -277,12 +277,10 @@ pin_project! {
}
tokio_thread_local!(static CURRENT: LocalData = const { LocalData {
- thread_id: Cell::new(None),
ctx: RcCell::new(),
} });
struct LocalData {
- thread_id: Cell<Option<ThreadId>>,
ctx: RcCell<Context>,
}
@@ -291,9 +289,9 @@ cfg_rt! {
///
/// The spawned future will run on the same thread that called `spawn_local`.
///
- /// You do not have to `.await` the returned `JoinHandle` to make the
- /// provided future start execution. It will start running in the background
- /// immediately when `spawn_local` is called.
+ /// The provided future will start running in the background immediately
+ /// when `spawn_local` is called, even if you don't await the returned
+ /// `JoinHandle`.
///
/// # Panics
///
@@ -379,12 +377,14 @@ impl fmt::Debug for LocalEnterGuard {
impl LocalSet {
/// Returns a new local task set.
pub fn new() -> LocalSet {
+ let owner = context::thread_id().expect("cannot create LocalSet during thread shutdown");
+
LocalSet {
tick: Cell::new(0),
context: Rc::new(Context {
shared: Arc::new(Shared {
local_state: LocalState {
- owner: thread_id().expect("cannot create LocalSet during thread shutdown"),
+ owner,
owned: LocalOwnedTasks::new(),
local_queue: UnsafeCell::new(VecDeque::with_capacity(INITIAL_CAPACITY)),
},
@@ -417,10 +417,9 @@ impl LocalSet {
/// This task is guaranteed to be run on the current thread.
///
/// Unlike the free function [`spawn_local`], this method may be used to
- /// spawn local tasks when the `LocalSet` is _not_ running. You do not have
- /// to `.await` the returned `JoinHandle` to make the provided future start
- /// execution. It will start running immediately whenever the `LocalSet` is
- /// next started.
+ /// spawn local tasks when the `LocalSet` is _not_ running. The provided
+ /// future will start running once the `LocalSet` is next started, even if
+ /// you don't await the returned `JoinHandle`.
///
/// # Examples
///
@@ -949,7 +948,7 @@ impl Shared {
// We are on the thread that owns the `LocalSet`, so we can
// wake to the local queue.
- _ if localdata.get_id() == Some(self.local_state.owner) => {
+ _ if context::thread_id().ok() == Some(self.local_state.owner) => {
unsafe {
// Safety: we just checked that the thread ID matches
// the localset's owner, so this is safe.
@@ -1093,7 +1092,9 @@ impl LocalState {
// if we couldn't get the thread ID because we're dropping the local
// data, skip the assertion --- the `Drop` impl is not going to be
// called from another thread, because `LocalSet` is `!Send`
- thread_id().map(|id| id == self.owner).unwrap_or(true),
+ context::thread_id()
+ .map(|id| id == self.owner)
+ .unwrap_or(true),
"`LocalSet`'s local run queue must not be accessed by another thread!"
);
}
@@ -1103,26 +1104,6 @@ impl LocalState {
// ensure they are on the same thread that owns the `LocalSet`.
unsafe impl Send for LocalState {}
-impl LocalData {
- fn get_id(&self) -> Option<ThreadId> {
- self.thread_id.get()
- }
-
- fn get_or_insert_id(&self) -> ThreadId {
- self.thread_id.get().unwrap_or_else(|| {
- let id = thread::current().id();
- self.thread_id.set(Some(id));
- id
- })
- }
-}
-
-fn thread_id() -> Option<ThreadId> {
- CURRENT
- .try_with(|localdata| localdata.get_or_insert_id())
- .ok()
-}
-
#[cfg(all(test, not(loom)))]
mod tests {
use super::*;