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:🧵: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: - rust-lang/rust#29457 - rust-lang/rust#29448 - rust-lang/rust#29447 And this in the RFC repo: rust-lang/rfcs#1435
This commit is contained in:
commit
6d620843f6
@ -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<CString>, // Guaranteed to be UTF-8
|
||||
id: ThreadId,
|
||||
lock: Mutex<bool>, // 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.
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user