Skip to content

Commit 6d62084

Browse files
authoredOct 10, 2016
Auto merge of #36341 - sagebind:thread_id, r=alexcrichton
Add ThreadId for comparing threads This adds the capability to store and compare threads with the current calling thread via a new struct, `std::thread::ThreadId`. Addresses the need outlined in issue #21507. This avoids the need to add any special checks to the existing thread structs and does not rely on the system to provide an identifier for a thread, since it seems that this approach is unreliable and undesirable. Instead, this simply uses a lazily-created, thread-local `usize` whose value is copied from a global atomic counter. The code should be simple enough that it should be as much reliable as the `#[thread_local]` attribute it uses (however much that is). `ThreadId`s can be compared directly for equality and have copy semantics. Also see these other attempts: - #29457 - #29448 - #29447 And this in the RFC repo: rust-lang/rfcs#1435
2 parents a7bfb1a + 032bffa commit 6d62084

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed
 

‎src/libstd/thread/mod.rs

+59
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ use panicking;
166166
use str;
167167
use sync::{Mutex, Condvar, Arc};
168168
use sys::thread as imp;
169+
use sys_common::mutex;
169170
use sys_common::thread_info;
170171
use sys_common::util;
171172
use sys_common::{AsInner, IntoInner};
@@ -524,13 +525,53 @@ pub fn park_timeout(dur: Duration) {
524525
*guard = false;
525526
}
526527

528+
////////////////////////////////////////////////////////////////////////////////
529+
// ThreadId
530+
////////////////////////////////////////////////////////////////////////////////
531+
532+
/// A unique identifier for a running thread.
533+
///
534+
/// A `ThreadId` is an opaque object that has a unique value for each thread
535+
/// that creates one. `ThreadId`s do not correspond to a thread's system-
536+
/// designated identifier.
537+
#[unstable(feature = "thread_id", issue = "21507")]
538+
#[derive(Eq, PartialEq, Copy, Clone)]
539+
pub struct ThreadId(u64);
540+
541+
impl ThreadId {
542+
// Generate a new unique thread ID.
543+
fn new() -> ThreadId {
544+
static GUARD: mutex::Mutex = mutex::Mutex::new();
545+
static mut COUNTER: u64 = 0;
546+
547+
unsafe {
548+
GUARD.lock();
549+
550+
// If we somehow use up all our bits, panic so that we're not
551+
// covering up subtle bugs of IDs being reused.
552+
if COUNTER == ::u64::MAX {
553+
GUARD.unlock();
554+
panic!("failed to generate unique thread ID: bitspace exhausted");
555+
}
556+
557+
let id = COUNTER;
558+
COUNTER += 1;
559+
560+
GUARD.unlock();
561+
562+
ThreadId(id)
563+
}
564+
}
565+
}
566+
527567
////////////////////////////////////////////////////////////////////////////////
528568
// Thread
529569
////////////////////////////////////////////////////////////////////////////////
530570

531571
/// The internal representation of a `Thread` handle
532572
struct Inner {
533573
name: Option<CString>, // Guaranteed to be UTF-8
574+
id: ThreadId,
534575
lock: Mutex<bool>, // true when there is a buffered unpark
535576
cvar: Condvar,
536577
}
@@ -551,6 +592,7 @@ impl Thread {
551592
Thread {
552593
inner: Arc::new(Inner {
553594
name: cname,
595+
id: ThreadId::new(),
554596
lock: Mutex::new(false),
555597
cvar: Condvar::new(),
556598
})
@@ -569,6 +611,12 @@ impl Thread {
569611
}
570612
}
571613

614+
/// Gets the thread's unique identifier.
615+
#[unstable(feature = "thread_id", issue = "21507")]
616+
pub fn id(&self) -> ThreadId {
617+
self.inner.id
618+
}
619+
572620
/// Gets the thread's name.
573621
///
574622
/// # Examples
@@ -977,6 +1025,17 @@ mod tests {
9771025
thread::sleep(Duration::from_millis(2));
9781026
}
9791027

1028+
#[test]
1029+
fn test_thread_id_equal() {
1030+
assert!(thread::current().id() == thread::current().id());
1031+
}
1032+
1033+
#[test]
1034+
fn test_thread_id_not_equal() {
1035+
let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap();
1036+
assert!(thread::current().id() != spawned_id);
1037+
}
1038+
9801039
// NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due
9811040
// to the test harness apparently interfering with stderr configuration.
9821041
}

0 commit comments

Comments
 (0)
Please sign in to comment.