-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Add ThreadId for comparing threads #36341
Changes from 2 commits
5bd834b
6e10e29
894ef96
e80fd25
032bffa
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 |
---|---|---|
|
@@ -165,6 +165,7 @@ use panic; | |
use panicking; | ||
use str; | ||
use sync::{Mutex, Condvar, Arc}; | ||
use sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; | ||
use sys::thread as imp; | ||
use sys_common::thread_info; | ||
use sys_common::util; | ||
|
@@ -524,6 +525,35 @@ pub fn park_timeout(dur: Duration) { | |
*guard = false; | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////////////// | ||
// ThreadId | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
||
/// A unique identifier for a running thread. | ||
/// | ||
/// A `ThreadId` is an opaque object that has a unique value for each thread | ||
/// that creates one. `ThreadId`s do not correspond to a thread's system- | ||
/// designated identifier. | ||
#[unstable(feature = "thread_id", issue = "21507")] | ||
#[derive(Eq, PartialEq, Copy, Clone)] | ||
pub struct ThreadId(usize); | ||
|
||
impl ThreadId { | ||
/// Returns an identifier unique to the current calling thread. | ||
#[unstable(feature = "thread_id", issue = "21507")] | ||
pub fn current() -> ThreadId { | ||
static THREAD_ID_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; | ||
#[thread_local] static mut THREAD_ID: ThreadId = ThreadId(0); | ||
|
||
unsafe { | ||
if THREAD_ID.0 == 0 { | ||
THREAD_ID.0 = 1 + THREAD_ID_COUNT.fetch_add(1, Ordering::SeqCst); | ||
} | ||
THREAD_ID | ||
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. This implementation allows for two distinct threads to have a same ID in some cases. 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. What case is that? 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. At least
To explain it, consider a 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. That's the only possibility for collision that I thought of. Would it be better to use a u64? If the number of threads you are creating is overflowing a 64 bits (highly unlikely, IMO), then there's not much we can really do, is there? What possible representation could we even use for thread IDs in that case? I can't imagine an OS being able to even handle up to u64-1 threads. 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. Not that Java is something I look up to, but here's how Java implements unique thread IDs: private static synchronized long nextThreadID() {
return ++threadSeqNumber;
} My gut intuition (without doing any calculating) is that It would take thousands of years of running for a loop like that spawning threads to overflow 64 bits. Highly unlikely. 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.
You’re assuming that all the threads should be alive at the same time in order for the collision to happen, which is simply not true.
Yes it would. At least then it wouldn’t take a
Using the address of something unique to a thread in the address space common to all threads would be one way to get guarantee that thread IDs would not collide. (see #29448 (comment) though) 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. A similar issue exists for reference counted pointers. As pointed out in that discussion, you don't actually need to run a googol increment instructions to overflow, if LLVM optimizes the relevant loop (this is certainly possible for |
||
} | ||
} | ||
} | ||
|
||
//////////////////////////////////////////////////////////////////////////////// | ||
// Thread | ||
//////////////////////////////////////////////////////////////////////////////// | ||
|
@@ -977,6 +1007,16 @@ mod tests { | |
thread::sleep(Duration::from_millis(2)); | ||
} | ||
|
||
#[test] | ||
fn test_thread_id_equal() { | ||
assert!(thread::ThreadId::current() == thread::ThreadId::current()); | ||
} | ||
|
||
#[test] | ||
fn test_thread_id_not_equal() { | ||
assert!(thread::ThreadId::current() != thread::spawn(|| thread::ThreadId::current()).join().unwrap()); | ||
} | ||
|
||
// NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due | ||
// to the test harness apparently interfering with stderr configuration. | ||
} |
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.
thread_local!
?isn't
#[thread_local]
unsupported on some platforms?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.
My understanding was that the
thread_local!
macro was implemented using#[thread_local]
, but that may not be the case.Since the value is atomic already, the complicated mutexes, keys, and locking provided by
thread_local!
I felt were unnecessary overhead.