diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index d8e021bb04ff9..98feea96f8c49 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -166,6 +166,7 @@ use panicking; use str; use sync::{Mutex, Condvar, Arc}; use sys::thread as imp; +use sys_common::mutex; use sys_common::thread_info; use sys_common::util; use sys_common::{AsInner, IntoInner}; @@ -524,6 +525,45 @@ 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(u64); + +impl ThreadId { + // Generate a new unique thread ID. + fn new() -> ThreadId { + static GUARD: mutex::Mutex = mutex::Mutex::new(); + static mut COUNTER: u64 = 0; + + unsafe { + GUARD.lock(); + + // If we somehow use up all our bits, panic so that we're not + // covering up subtle bugs of IDs being reused. + if COUNTER == ::u64::MAX { + GUARD.unlock(); + panic!("failed to generate unique thread ID: bitspace exhausted"); + } + + let id = COUNTER; + COUNTER += 1; + + GUARD.unlock(); + + ThreadId(id) + } + } +} + //////////////////////////////////////////////////////////////////////////////// // Thread //////////////////////////////////////////////////////////////////////////////// @@ -531,6 +571,7 @@ pub fn park_timeout(dur: Duration) { /// The internal representation of a `Thread` handle struct Inner { name: Option, // Guaranteed to be UTF-8 + id: ThreadId, lock: Mutex, // true when there is a buffered unpark cvar: Condvar, } @@ -551,6 +592,7 @@ impl Thread { Thread { inner: Arc::new(Inner { name: cname, + id: ThreadId::new(), lock: Mutex::new(false), cvar: Condvar::new(), }) @@ -569,6 +611,12 @@ impl Thread { } } + /// Gets the thread's unique identifier. + #[unstable(feature = "thread_id", issue = "21507")] + pub fn id(&self) -> ThreadId { + self.inner.id + } + /// Gets the thread's name. /// /// # Examples @@ -977,6 +1025,17 @@ mod tests { thread::sleep(Duration::from_millis(2)); } + #[test] + fn test_thread_id_equal() { + assert!(thread::current().id() == thread::current().id()); + } + + #[test] + fn test_thread_id_not_equal() { + let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap(); + assert!(thread::current().id() != spawned_id); + } + // NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due // to the test harness apparently interfering with stderr configuration. }