-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use ThreadId instead of TLS-address in ReentrantLock
#124881
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -159,7 +159,7 @@ | |
mod tests; | ||
|
||
use crate::any::Any; | ||
use crate::cell::{OnceCell, UnsafeCell}; | ||
use crate::cell::{Cell, OnceCell, UnsafeCell}; | ||
use crate::env; | ||
use crate::ffi::{CStr, CString}; | ||
use crate::fmt; | ||
|
@@ -698,17 +698,22 @@ where | |
} | ||
|
||
thread_local! { | ||
// Invariant: `CURRENT` and `CURRENT_ID` will always be initialized together. | ||
// If `CURRENT` is initialized, then `CURRENT_ID` will hold the same value | ||
// as `CURRENT.id()`. | ||
static CURRENT: OnceCell<Thread> = const { OnceCell::new() }; | ||
static CURRENT_ID: Cell<Option<ThreadId>> = const { Cell::new(None) }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So now we redundantly store the thread ID twice, once in the At least we should explicitly document this invariant. Ideally we can avoid the redundancy... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure the redundancy can be avoided, seeing as we want to access the thread local without accessing the |
||
} | ||
|
||
/// Sets the thread handle for the current thread. | ||
/// | ||
/// Aborts if the handle has been set already to reduce code size. | ||
pub(crate) fn set_current(thread: Thread) { | ||
let tid = thread.id(); | ||
// Using `unwrap` here can add ~3kB to the binary size. We have complete | ||
// control over where this is called, so just abort if there is a bug. | ||
CURRENT.with(|current| match current.set(thread) { | ||
Ok(()) => {} | ||
Ok(()) => CURRENT_ID.set(Some(tid)), | ||
Err(_) => rtabort!("thread::set_current should only be called once per thread"), | ||
}); | ||
} | ||
|
@@ -718,7 +723,28 @@ pub(crate) fn set_current(thread: Thread) { | |
/// In contrast to the public `current` function, this will not panic if called | ||
/// from inside a TLS destructor. | ||
pub(crate) fn try_current() -> Option<Thread> { | ||
CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok() | ||
CURRENT | ||
.try_with(|current| { | ||
current | ||
.get_or_init(|| { | ||
let thread = Thread::new_unnamed(); | ||
CURRENT_ID.set(Some(thread.id())); | ||
thread | ||
}) | ||
.clone() | ||
}) | ||
.ok() | ||
} | ||
|
||
/// Gets the id of the thread that invokes it. | ||
#[inline] | ||
pub(crate) fn current_id() -> ThreadId { | ||
CURRENT_ID.get().unwrap_or_else(|| { | ||
// If `CURRENT_ID` isn't initialized yet, then `CURRENT` must also not be initialized. | ||
// `current()` will initialize both `CURRENT` and `CURRENT_ID` so subsequent calls to | ||
// `current_id()` will succeed immediately. | ||
current().id() | ||
}) | ||
} | ||
|
||
/// Gets a handle to the thread that invokes it. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also add a note about
CURRENT_ID
always holding the same ID as the thread inCURRENT
, if it is initialized?