]> git.proxmox.com Git - rustc.git/blame - src/libstd/thread/mod.rs
New upstream version 1.17.0+dfsg2
[rustc.git] / src / libstd / thread / mod.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
54a0048b 11//! Native threads.
1a4d82fc
JJ
12//!
13//! ## The threading model
14//!
15//! An executing Rust program consists of a collection of native OS threads,
a7813a04
XL
16//! each with their own stack and local state. Threads can be named, and
17//! provide some built-in support for low-level synchronization.
1a4d82fc
JJ
18//!
19//! Communication between threads can be done through
476ff2be 20//! [channels], Rust's message-passing types, along with [other forms of thread
1a4d82fc
JJ
21//! synchronization](../../std/sync/index.html) and shared-memory data
22//! structures. In particular, types that are guaranteed to be
23//! threadsafe are easily shared between threads using the
476ff2be 24//! atomically-reference-counted container, [`Arc`].
1a4d82fc
JJ
25//!
26//! Fatal logic errors in Rust cause *thread panic*, during which
27//! a thread will unwind the stack, running destructors and freeing
28//! owned resources. Thread panic is unrecoverable from within
29//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
c34b1796
AL
30//! the panic may optionally be detected from a different thread. If
31//! the main thread panics, the application will exit with a non-zero
1a4d82fc
JJ
32//! exit code.
33//!
34//! When the main thread of a Rust program terminates, the entire program shuts
35//! down, even if other threads are still running. However, this module provides
36//! convenient facilities for automatically waiting for the termination of a
c34b1796 37//! child thread (i.e., join).
1a4d82fc 38//!
1a4d82fc
JJ
39//! ## Spawning a thread
40//!
476ff2be 41//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function:
1a4d82fc
JJ
42//!
43//! ```rust
85aaf69f 44//! use std::thread;
1a4d82fc 45//!
85aaf69f 46//! thread::spawn(move || {
c34b1796 47//! // some work here
1a4d82fc
JJ
48//! });
49//! ```
50//!
85aaf69f 51//! In this example, the spawned thread is "detached" from the current
c34b1796
AL
52//! thread. This means that it can outlive its parent (the thread that spawned
53//! it), unless this parent is the main thread.
1a4d82fc 54//!
9346a6ac 55//! The parent thread can also wait on the completion of the child
476ff2be 56//! thread; a call to [`spawn`] produces a [`JoinHandle`], which provides
9346a6ac
AL
57//! a `join` method for waiting:
58//!
59//! ```rust
60//! use std::thread;
61//!
62//! let child = thread::spawn(move || {
63//! // some work here
64//! });
65//! // some work here
66//! let res = child.join();
67//! ```
68//!
476ff2be
SL
69//! The [`join`] method returns a [`Result`] containing [`Ok`] of the final
70//! value produced by the child thread, or [`Err`] of the value given to
71//! a call to [`panic!`] if the child panicked.
9346a6ac 72//!
1a4d82fc
JJ
73//! ## Configuring threads
74//!
476ff2be 75//! A new thread can be configured before it is spawned via the [`Builder`] type,
bd371182 76//! which currently allows you to set the name and stack size for the child thread:
1a4d82fc
JJ
77//!
78//! ```rust
9346a6ac 79//! # #![allow(unused_must_use)]
1a4d82fc
JJ
80//! use std::thread;
81//!
82//! thread::Builder::new().name("child1".to_string()).spawn(move || {
c34b1796 83//! println!("Hello, world!");
1a4d82fc
JJ
84//! });
85//! ```
86//!
a7813a04
XL
87//! ## The `Thread` type
88//!
476ff2be 89//! Threads are represented via the [`Thread`] type, which you can get in one of
a7813a04
XL
90//! two ways:
91//!
476ff2be
SL
92//! * By spawning a new thread, e.g. using the [`thread::spawn`][`spawn`]
93//! function, and calling [`thread()`] on the [`JoinHandle`].
94//! * By requesting the current thread, using the [`thread::current()`] function.
a7813a04 95//!
476ff2be 96//! The [`thread::current()`] function is available even for threads not spawned
a7813a04
XL
97//! by the APIs of this module.
98//!
1a4d82fc
JJ
99//! ## Blocking support: park and unpark
100//!
101//! Every thread is equipped with some basic low-level blocking support, via the
476ff2be
SL
102//! [`thread::park()`][`park()`] function and [`thread::Thread::unpark()`][`unpark()`]
103//! method. [`park()`] blocks the current thread, which can then be resumed from
104//! another thread by calling the [`unpark()`] method on the blocked thread's handle.
1a4d82fc 105//!
476ff2be 106//! Conceptually, each [`Thread`] handle has an associated token, which is
1a4d82fc
JJ
107//! initially not present:
108//!
476ff2be 109//! * The [`thread::park()`][`park()`] function blocks the current thread unless or until
c34b1796 110//! the token is available for its thread handle, at which point it atomically
1a4d82fc 111//! consumes the token. It may also return *spuriously*, without consuming the
476ff2be 112//! token. [`thread::park_timeout()`] does the same, but allows specifying a
85aaf69f 113//! maximum time to block the thread for.
1a4d82fc 114//!
476ff2be 115//! * The [`unpark()`] method on a [`Thread`] atomically makes the token available
1a4d82fc
JJ
116//! if it wasn't already.
117//!
476ff2be 118//! In other words, each [`Thread`] acts a bit like a semaphore with initial count
1a4d82fc
JJ
119//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
120//! and can return spuriously.
121//!
122//! The API is typically used by acquiring a handle to the current thread,
123//! placing that handle in a shared data structure so that other threads can
124//! find it, and then `park`ing. When some desired condition is met, another
476ff2be 125//! thread calls [`unpark()`] on the handle.
1a4d82fc
JJ
126//!
127//! The motivation for this design is twofold:
128//!
129//! * It avoids the need to allocate mutexes and condvars when building new
130//! synchronization primitives; the threads already provide basic blocking/signaling.
131//!
c34b1796
AL
132//! * It can be implemented very efficiently on many platforms.
133//!
134//! ## Thread-local storage
135//!
9e0c209e
SL
136//! This module also provides an implementation of thread-local storage for Rust
137//! programs. Thread-local storage is a method of storing data into a global
138//! variable that each thread in the program will have its own copy of.
c34b1796
AL
139//! Threads do not share this data, so accesses do not need to be synchronized.
140//!
9e0c209e
SL
141//! A thread-local key owns the value it contains and will destroy the value when the
142//! thread exits. It is created with the [`thread_local!`] macro and can contain any
143//! value that is `'static` (no borrowed pointers). It provides an accessor function,
144//! [`with`], that yields a shared reference to the value to the specified
145//! closure. Thread-local keys allow only shared access to values, as there would be no
146//! way to guarantee uniqueness if mutable borrows were allowed. Most values
c34b1796 147//! will want to make use of some form of **interior mutability** through the
9e0c209e
SL
148//! [`Cell`] or [`RefCell`] types.
149//!
476ff2be
SL
150//! [channels]: ../../std/sync/mpsc/index.html
151//! [`Arc`]: ../../std/sync/struct.Arc.html
152//! [`spawn`]: ../../std/thread/fn.spawn.html
153//! [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
154//! [`thread()`]: ../../std/thread/struct.JoinHandle.html#method.thread
155//! [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
156//! [`Result`]: ../../std/result/enum.Result.html
157//! [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
158//! [`Err`]: ../../std/result/enum.Result.html#variant.Err
159//! [`panic!`]: ../../std/macro.panic.html
160//! [`Builder`]: ../../std/thread/struct.Builder.html
161//! [`thread::current()`]: ../../std/thread/fn.spawn.html
162//! [`Thread`]: ../../std/thread/struct.Thread.html
163//! [`park()`]: ../../std/thread/fn.park.html
164//! [`unpark()`]: ../../std/thread/struct.Thread.html#method.unpark
165//! [`thread::park_timeout()`]: ../../std/thread/fn.park_timeout.html
9e0c209e
SL
166//! [`Cell`]: ../cell/struct.Cell.html
167//! [`RefCell`]: ../cell/struct.RefCell.html
c30ab7b3 168//! [`thread_local!`]: ../macro.thread_local.html
9e0c209e 169//! [`with`]: struct.LocalKey.html#method.with
1a4d82fc 170
85aaf69f
SL
171#![stable(feature = "rust1", since = "1.0.0")]
172
1a4d82fc 173use any::Any;
1a4d82fc 174use cell::UnsafeCell;
a7813a04 175use ffi::{CStr, CString};
85aaf69f
SL
176use fmt;
177use io;
a7813a04
XL
178use panic;
179use panicking;
54a0048b 180use str;
85aaf69f 181use sync::{Mutex, Condvar, Arc};
c34b1796 182use sys::thread as imp;
c30ab7b3 183use sys_common::mutex;
e9174d1e 184use sys_common::thread_info;
e9174d1e 185use sys_common::util;
92a42be0 186use sys_common::{AsInner, IntoInner};
85aaf69f 187use time::Duration;
1a4d82fc 188
c34b1796
AL
189////////////////////////////////////////////////////////////////////////////////
190// Thread-local storage
191////////////////////////////////////////////////////////////////////////////////
192
9346a6ac 193#[macro_use] mod local;
9346a6ac
AL
194
195#[stable(feature = "rust1", since = "1.0.0")]
196pub use self::local::{LocalKey, LocalKeyState};
197
c30ab7b3
SL
198// The types used by the thread_local! macro to access TLS keys. Note that there
199// are two types, the "OS" type and the "fast" type. The OS thread local key
200// type is accessed via platform-specific API calls and is slow, while the fast
201// key type is accessed via code generated via LLVM, where TLS keys are set up
202// by the elf linker. Note that the OS TLS type is always available: on macOS
203// the standard library is compiled with support for older platform versions
204// where fast TLS was not available; end-user code is compiled with fast TLS
205// where available, but both are needed.
206
92a42be0 207#[unstable(feature = "libstd_thread_internals", issue = "0")]
9cc50fc6 208#[cfg(target_thread_local)]
c30ab7b3 209#[doc(hidden)] pub use sys::fast_thread_local::Key as __FastLocalKeyInner;
9cc50fc6
SL
210#[unstable(feature = "libstd_thread_internals", issue = "0")]
211#[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
c34b1796
AL
212
213////////////////////////////////////////////////////////////////////////////////
214// Builder
215////////////////////////////////////////////////////////////////////////////////
1a4d82fc
JJ
216
217/// Thread configuration. Provides detailed control over the properties
218/// and behavior of new threads.
32a655c1
SL
219///
220/// # Examples
221///
222/// ```
223/// use std::thread;
224///
225/// let builder = thread::Builder::new();
226///
227/// let handler = builder.spawn(|| {
228/// // thread code
229/// }).unwrap();
230///
231/// handler.join().unwrap();
232/// ```
85aaf69f 233#[stable(feature = "rust1", since = "1.0.0")]
32a655c1 234#[derive(Debug)]
1a4d82fc
JJ
235pub struct Builder {
236 // A name for the thread-to-be, for identification in panic messages
237 name: Option<String>,
8bb4bdeb 238 // The size of the stack for the spawned thread in bytes
c34b1796 239 stack_size: Option<usize>,
1a4d82fc
JJ
240}
241
242impl Builder {
9346a6ac 243 /// Generates the base configuration for spawning a thread, from which
1a4d82fc 244 /// configuration methods can be chained.
32a655c1
SL
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use std::thread;
250 ///
251 /// let builder = thread::Builder::new()
252 /// .name("foo".into())
253 /// .stack_size(10);
254 ///
255 /// let handler = builder.spawn(|| {
256 /// // thread code
257 /// }).unwrap();
258 ///
259 /// handler.join().unwrap();
260 /// ```
85aaf69f 261 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
262 pub fn new() -> Builder {
263 Builder {
264 name: None,
265 stack_size: None,
1a4d82fc
JJ
266 }
267 }
268
9346a6ac 269 /// Names the thread-to-be. Currently the name is used for identification
1a4d82fc 270 /// only in panic messages.
3157f602
XL
271 ///
272 /// # Examples
273 ///
32a655c1 274 /// ```
3157f602
XL
275 /// use std::thread;
276 ///
277 /// let builder = thread::Builder::new()
278 /// .name("foo".into());
279 ///
280 /// let handler = builder.spawn(|| {
281 /// assert_eq!(thread::current().name(), Some("foo"))
282 /// }).unwrap();
283 ///
284 /// handler.join().unwrap();
285 /// ```
85aaf69f 286 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
287 pub fn name(mut self, name: String) -> Builder {
288 self.name = Some(name);
289 self
290 }
291
8bb4bdeb
XL
292 /// Sets the size of the stack (in bytes) for the new thread.
293 ///
294 /// The actual stack size may be greater than this value if
295 /// the platform specifies minimal stack size.
32a655c1
SL
296 ///
297 /// # Examples
298 ///
299 /// ```
300 /// use std::thread;
301 ///
8bb4bdeb 302 /// let builder = thread::Builder::new().stack_size(32 * 1024);
32a655c1 303 /// ```
85aaf69f 304 #[stable(feature = "rust1", since = "1.0.0")]
c34b1796 305 pub fn stack_size(mut self, size: usize) -> Builder {
1a4d82fc
JJ
306 self.stack_size = Some(size);
307 self
308 }
309
9346a6ac 310 /// Spawns a new thread, and returns a join handle for it.
1a4d82fc 311 ///
85aaf69f
SL
312 /// The child thread may outlive the parent (unless the parent thread
313 /// is the main thread; the whole process is terminated when the main
bd371182 314 /// thread finishes). The join handle can be used to block on
85aaf69f
SL
315 /// termination of the child thread, including recovering its panics.
316 ///
317 /// # Errors
318 ///
32a655c1
SL
319 /// Unlike the [`spawn`] free function, this method yields an
320 /// [`io::Result`] to capture any failure to create the thread at
85aaf69f 321 /// the OS level.
32a655c1
SL
322 ///
323 /// [`spawn`]: ../../std/thread/fn.spawn.html
324 /// [`io::Result`]: ../../std/io/type.Result.html
325 ///
326 /// # Examples
327 ///
328 /// ```
329 /// use std::thread;
330 ///
331 /// let builder = thread::Builder::new();
332 ///
333 /// let handler = builder.spawn(|| {
334 /// // thread code
335 /// }).unwrap();
336 ///
337 /// handler.join().unwrap();
338 /// ```
85aaf69f 339 #[stable(feature = "rust1", since = "1.0.0")]
9346a6ac
AL
340 pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
341 F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
85aaf69f 342 {
c34b1796 343 let Builder { name, stack_size } = self;
1a4d82fc 344
e9174d1e 345 let stack_size = stack_size.unwrap_or(util::min_stack());
85aaf69f 346
1a4d82fc
JJ
347 let my_thread = Thread::new(name);
348 let their_thread = my_thread.clone();
349
b039eaaf
SL
350 let my_packet : Arc<UnsafeCell<Option<Result<T>>>>
351 = Arc::new(UnsafeCell::new(None));
d9579d0f 352 let their_packet = my_packet.clone();
85aaf69f 353
85aaf69f 354 let main = move || {
54a0048b 355 if let Some(name) = their_thread.cname() {
d9579d0f 356 imp::Thread::set_name(name);
85aaf69f 357 }
b039eaaf
SL
358 unsafe {
359 thread_info::set(imp::guard::current(), their_thread);
a7813a04
XL
360 let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
361 *their_packet.get() = Some(try_result);
b039eaaf 362 }
1a4d82fc
JJ
363 };
364
b039eaaf
SL
365 Ok(JoinHandle(JoinInner {
366 native: unsafe {
54a0048b 367 Some(imp::Thread::new(stack_size, Box::new(main))?)
b039eaaf 368 },
85aaf69f 369 thread: my_thread,
d9579d0f 370 packet: Packet(my_packet),
b039eaaf 371 }))
1a4d82fc
JJ
372 }
373}
374
c34b1796
AL
375////////////////////////////////////////////////////////////////////////////////
376// Free functions
377////////////////////////////////////////////////////////////////////////////////
378
32a655c1 379/// Spawns a new thread, returning a [`JoinHandle`] for it.
85aaf69f 380///
c34b1796
AL
381/// The join handle will implicitly *detach* the child thread upon being
382/// dropped. In this case, the child thread may outlive the parent (unless
383/// the parent thread is the main thread; the whole process is terminated when
32a655c1 384/// the main thread finishes). Additionally, the join handle provides a [`join`]
c34b1796 385/// method that can be used to join the child thread. If the child thread
32a655c1
SL
386/// panics, [`join`] will return an [`Err`] containing the argument given to
387/// [`panic`].
85aaf69f
SL
388///
389/// # Panics
390///
32a655c1 391/// Panics if the OS fails to create a thread; use [`Builder::spawn`]
85aaf69f 392/// to recover from such errors.
32a655c1
SL
393///
394/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
395/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
396/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
397/// [`panic`]: ../../std/macro.panic.html
398/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
399///
400/// # Examples
401///
402/// ```
403/// use std::thread;
404///
405/// let handler = thread::spawn(|| {
406/// // thread code
407/// });
408///
409/// handler.join().unwrap();
410/// ```
85aaf69f 411#[stable(feature = "rust1", since = "1.0.0")]
9346a6ac
AL
412pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
413 F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
414{
85aaf69f
SL
415 Builder::new().spawn(f).unwrap()
416}
417
85aaf69f 418/// Gets a handle to the thread that invokes it.
9e0c209e 419///
32a655c1 420/// # Examples
9e0c209e
SL
421///
422/// Getting a handle to the current thread with `thread::current()`:
423///
424/// ```
425/// use std::thread;
426///
427/// let handler = thread::Builder::new()
428/// .name("named thread".into())
429/// .spawn(|| {
430/// let handle = thread::current();
431/// assert_eq!(handle.name(), Some("named thread"));
432/// })
433/// .unwrap();
434///
435/// handler.join().unwrap();
436/// ```
85aaf69f
SL
437#[stable(feature = "rust1", since = "1.0.0")]
438pub fn current() -> Thread {
d9579d0f
AL
439 thread_info::current_thread().expect("use of std::thread::current() is not \
440 possible after the thread's local \
441 data has been destroyed")
85aaf69f
SL
442}
443
9346a6ac 444/// Cooperatively gives up a timeslice to the OS scheduler.
32a655c1
SL
445///
446/// # Examples
447///
448/// ```
449/// use std::thread;
450///
451/// thread::yield_now();
452/// ```
85aaf69f
SL
453#[stable(feature = "rust1", since = "1.0.0")]
454pub fn yield_now() {
d9579d0f 455 imp::Thread::yield_now()
85aaf69f
SL
456}
457
458/// Determines whether the current thread is unwinding because of panic.
3157f602
XL
459///
460/// # Examples
461///
32a655c1 462/// ```should_panic
3157f602
XL
463/// use std::thread;
464///
465/// struct SomeStruct;
466///
467/// impl Drop for SomeStruct {
468/// fn drop(&mut self) {
469/// if thread::panicking() {
470/// println!("dropped while unwinding");
471/// } else {
472/// println!("dropped while not unwinding");
473/// }
474/// }
475/// }
476///
477/// {
478/// print!("a: ");
479/// let a = SomeStruct;
480/// }
481///
482/// {
483/// print!("b: ");
484/// let b = SomeStruct;
485/// panic!()
486/// }
487/// ```
85aaf69f
SL
488#[inline]
489#[stable(feature = "rust1", since = "1.0.0")]
490pub fn panicking() -> bool {
a7813a04 491 panicking::panicking()
85aaf69f
SL
492}
493
9346a6ac 494/// Puts the current thread to sleep for the specified amount of time.
c34b1796
AL
495///
496/// The thread may sleep longer than the duration specified due to scheduling
32a655c1
SL
497/// specifics or platform-dependent functionality.
498///
499/// # Platform behavior
500///
501/// On Unix platforms this function will not return early due to a
502/// signal being received or a spurious wakeup.
503///
504/// # Examples
505///
506/// ```no_run
507/// use std::thread;
508///
509/// // Let's sleep for 2 seconds:
510/// thread::sleep_ms(2000);
511/// ```
c34b1796 512#[stable(feature = "rust1", since = "1.0.0")]
92a42be0 513#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::sleep`")]
c34b1796 514pub fn sleep_ms(ms: u32) {
d9579d0f
AL
515 sleep(Duration::from_millis(ms as u64))
516}
517
518/// Puts the current thread to sleep for the specified amount of time.
519///
520/// The thread may sleep longer than the duration specified due to scheduling
521/// specifics or platform-dependent functionality.
522///
523/// # Platform behavior
524///
525/// On Unix platforms this function will not return early due to a
526/// signal being received or a spurious wakeup. Platforms which do not support
527/// nanosecond precision for sleeping will have `dur` rounded up to the nearest
528/// granularity of time they can sleep for.
3157f602
XL
529///
530/// # Examples
531///
32a655c1 532/// ```no_run
3157f602
XL
533/// use std::{thread, time};
534///
535/// let ten_millis = time::Duration::from_millis(10);
536/// let now = time::Instant::now();
537///
538/// thread::sleep(ten_millis);
539///
540/// assert!(now.elapsed() >= ten_millis);
541/// ```
e9174d1e 542#[stable(feature = "thread_sleep", since = "1.4.0")]
d9579d0f
AL
543pub fn sleep(dur: Duration) {
544 imp::Thread::sleep(dur)
c34b1796
AL
545}
546
c1a9b12d
SL
547/// Blocks unless or until the current thread's token is made available.
548///
549/// Every thread is equipped with some basic low-level blocking support, via
550/// the `park()` function and the [`unpark()`][unpark] method. These can be
551/// used as a more CPU-efficient implementation of a spinlock.
552///
553/// [unpark]: struct.Thread.html#method.unpark
554///
555/// The API is typically used by acquiring a handle to the current thread,
556/// placing that handle in a shared data structure so that other threads can
557/// find it, and then parking (in a loop with a check for the token actually
558/// being acquired).
559///
560/// A call to `park` does not guarantee that the thread will remain parked
561/// forever, and callers should be prepared for this possibility.
562///
563/// See the [module documentation][thread] for more detail.
85aaf69f 564///
c1a9b12d 565/// [thread]: index.html
85aaf69f
SL
566//
567// The implementation currently uses the trivial strategy of a Mutex+Condvar
568// with wakeup flag, which does not actually allow spurious wakeups. In the
569// future, this will be implemented in a more efficient way, perhaps along the lines of
570// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
571// or futuxes, and in either case may allow spurious wakeups.
572#[stable(feature = "rust1", since = "1.0.0")]
573pub fn park() {
574 let thread = current();
575 let mut guard = thread.inner.lock.lock().unwrap();
576 while !*guard {
577 guard = thread.inner.cvar.wait(guard).unwrap();
578 }
579 *guard = false;
580}
581
5bcae85e
SL
582/// Use [park_timeout].
583///
9346a6ac 584/// Blocks unless or until the current thread's token is made available or
85aaf69f
SL
585/// the specified duration has been reached (may wake spuriously).
586///
587/// The semantics of this function are equivalent to `park()` except that the
3157f602 588/// thread will be blocked for roughly no longer than `ms`. This method
85aaf69f
SL
589/// should not be used for precise timing due to anomalies such as
590/// preemption or platform differences that may not cause the maximum
3157f602 591/// amount of time waited to be precisely `ms` long.
85aaf69f 592///
5bcae85e
SL
593/// See the [module documentation][thread] for more detail.
594///
595/// [thread]: index.html
596/// [park_timeout]: fn.park_timeout.html
c34b1796 597#[stable(feature = "rust1", since = "1.0.0")]
92a42be0 598#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")]
c34b1796 599pub fn park_timeout_ms(ms: u32) {
d9579d0f
AL
600 park_timeout(Duration::from_millis(ms as u64))
601}
602
603/// Blocks unless or until the current thread's token is made available or
604/// the specified duration has been reached (may wake spuriously).
605///
606/// The semantics of this function are equivalent to `park()` except that the
3157f602 607/// thread will be blocked for roughly no longer than `dur`. This method
d9579d0f
AL
608/// should not be used for precise timing due to anomalies such as
609/// preemption or platform differences that may not cause the maximum
3157f602 610/// amount of time waited to be precisely `dur` long.
d9579d0f
AL
611///
612/// See the module doc for more detail.
613///
614/// # Platform behavior
615///
616/// Platforms which do not support nanosecond precision for sleeping will have
617/// `dur` rounded up to the nearest granularity of time they can sleep for.
5bcae85e
SL
618///
619/// # Example
620///
621/// Waiting for the complete expiration of the timeout:
622///
623/// ```rust,no_run
624/// use std::thread::park_timeout;
625/// use std::time::{Instant, Duration};
626///
627/// let timeout = Duration::from_secs(2);
628/// let beginning_park = Instant::now();
629/// park_timeout(timeout);
630///
631/// while beginning_park.elapsed() < timeout {
632/// println!("restarting park_timeout after {:?}", beginning_park.elapsed());
633/// let timeout = timeout - beginning_park.elapsed();
634/// park_timeout(timeout);
635/// }
636/// ```
e9174d1e 637#[stable(feature = "park_timeout", since = "1.4.0")]
d9579d0f 638pub fn park_timeout(dur: Duration) {
85aaf69f
SL
639 let thread = current();
640 let mut guard = thread.inner.lock.lock().unwrap();
641 if !*guard {
d9579d0f 642 let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
85aaf69f
SL
643 guard = g;
644 }
645 *guard = false;
646}
647
c30ab7b3
SL
648////////////////////////////////////////////////////////////////////////////////
649// ThreadId
650////////////////////////////////////////////////////////////////////////////////
651
652/// A unique identifier for a running thread.
653///
654/// A `ThreadId` is an opaque object that has a unique value for each thread
655/// that creates one. `ThreadId`s do not correspond to a thread's system-
656/// designated identifier.
32a655c1
SL
657///
658/// # Examples
659///
660/// ```
661/// #![feature(thread_id)]
662///
663/// use std::thread;
664///
665/// let handler = thread::Builder::new()
666/// .spawn(|| {
667/// let thread = thread::current();
668/// let thread_id = thread.id();
669/// })
670/// .unwrap();
671///
672/// handler.join().unwrap();
673/// ```
c30ab7b3
SL
674#[unstable(feature = "thread_id", issue = "21507")]
675#[derive(Eq, PartialEq, Copy, Clone)]
676pub struct ThreadId(u64);
677
678impl ThreadId {
679 // Generate a new unique thread ID.
680 fn new() -> ThreadId {
681 static GUARD: mutex::Mutex = mutex::Mutex::new();
682 static mut COUNTER: u64 = 0;
683
684 unsafe {
685 GUARD.lock();
686
687 // If we somehow use up all our bits, panic so that we're not
688 // covering up subtle bugs of IDs being reused.
689 if COUNTER == ::u64::MAX {
690 GUARD.unlock();
691 panic!("failed to generate unique thread ID: bitspace exhausted");
692 }
693
694 let id = COUNTER;
695 COUNTER += 1;
696
697 GUARD.unlock();
698
699 ThreadId(id)
700 }
701 }
702}
703
8bb4bdeb 704#[unstable(feature = "thread_id", issue = "21507")]
32a655c1
SL
705impl fmt::Debug for ThreadId {
706 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
707 f.pad("ThreadId { .. }")
708 }
709}
710
c34b1796
AL
711////////////////////////////////////////////////////////////////////////////////
712// Thread
713////////////////////////////////////////////////////////////////////////////////
714
85aaf69f 715/// The internal representation of a `Thread` handle
1a4d82fc 716struct Inner {
54a0048b 717 name: Option<CString>, // Guaranteed to be UTF-8
c30ab7b3 718 id: ThreadId,
1a4d82fc
JJ
719 lock: Mutex<bool>, // true when there is a buffered unpark
720 cvar: Condvar,
721}
722
1a4d82fc 723#[derive(Clone)]
85aaf69f 724#[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 725/// A handle to a thread.
32a655c1
SL
726///
727/// # Examples
728///
729/// ```
730/// use std::thread;
731///
732/// let handler = thread::Builder::new()
733/// .name("foo".into())
734/// .spawn(|| {
735/// let thread = thread::current();
736/// println!("thread name: {}", thread.name().unwrap());
737/// })
738/// .unwrap();
739///
740/// handler.join().unwrap();
741/// ```
1a4d82fc
JJ
742pub struct Thread {
743 inner: Arc<Inner>,
744}
745
746impl Thread {
747 // Used only internally to construct a thread object without spawning
748 fn new(name: Option<String>) -> Thread {
3157f602
XL
749 let cname = name.map(|n| {
750 CString::new(n).expect("thread name may not contain interior null bytes")
751 });
1a4d82fc
JJ
752 Thread {
753 inner: Arc::new(Inner {
54a0048b 754 name: cname,
c30ab7b3 755 id: ThreadId::new(),
1a4d82fc
JJ
756 lock: Mutex::new(false),
757 cvar: Condvar::new(),
758 })
759 }
760 }
761
1a4d82fc
JJ
762 /// Atomically makes the handle's token available if it is not already.
763 ///
764 /// See the module doc for more detail.
32a655c1
SL
765 ///
766 /// # Examples
767 ///
768 /// ```
769 /// use std::thread;
770 ///
771 /// let handler = thread::Builder::new()
772 /// .spawn(|| {
773 /// let thread = thread::current();
774 /// thread.unpark();
775 /// })
776 /// .unwrap();
777 ///
778 /// handler.join().unwrap();
779 /// ```
85aaf69f 780 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
781 pub fn unpark(&self) {
782 let mut guard = self.inner.lock.lock().unwrap();
783 if !*guard {
784 *guard = true;
785 self.inner.cvar.notify_one();
786 }
787 }
788
c30ab7b3 789 /// Gets the thread's unique identifier.
32a655c1
SL
790 ///
791 /// # Examples
792 ///
793 /// ```
794 /// #![feature(thread_id)]
795 ///
796 /// use std::thread;
797 ///
798 /// let handler = thread::Builder::new()
799 /// .spawn(|| {
800 /// let thread = thread::current();
801 /// println!("thread id: {:?}", thread.id());
802 /// })
803 /// .unwrap();
804 ///
805 /// handler.join().unwrap();
806 /// ```
c30ab7b3
SL
807 #[unstable(feature = "thread_id", issue = "21507")]
808 pub fn id(&self) -> ThreadId {
809 self.inner.id
810 }
811
9346a6ac 812 /// Gets the thread's name.
3157f602
XL
813 ///
814 /// # Examples
815 ///
816 /// Threads by default have no name specified:
817 ///
818 /// ```
819 /// use std::thread;
820 ///
821 /// let builder = thread::Builder::new();
822 ///
823 /// let handler = builder.spawn(|| {
824 /// assert!(thread::current().name().is_none());
825 /// }).unwrap();
826 ///
827 /// handler.join().unwrap();
828 /// ```
829 ///
830 /// Thread with a specified name:
831 ///
832 /// ```
833 /// use std::thread;
834 ///
835 /// let builder = thread::Builder::new()
836 /// .name("foo".into());
837 ///
838 /// let handler = builder.spawn(|| {
839 /// assert_eq!(thread::current().name(), Some("foo"))
840 /// }).unwrap();
841 ///
842 /// handler.join().unwrap();
843 /// ```
85aaf69f 844 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 845 pub fn name(&self) -> Option<&str> {
54a0048b
SL
846 self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) } )
847 }
848
849 fn cname(&self) -> Option<&CStr> {
85aaf69f
SL
850 self.inner.name.as_ref().map(|s| &**s)
851 }
852}
853
854#[stable(feature = "rust1", since = "1.0.0")]
855impl fmt::Debug for Thread {
856 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
857 fmt::Debug::fmt(&self.name(), f)
1a4d82fc
JJ
858 }
859}
860
861// a hack to get around privacy restrictions
862impl thread_info::NewThread for Thread {
863 fn new(name: Option<String>) -> Thread { Thread::new(name) }
864}
865
c34b1796 866////////////////////////////////////////////////////////////////////////////////
e9174d1e 867// JoinHandle
c34b1796
AL
868////////////////////////////////////////////////////////////////////////////////
869
1a4d82fc
JJ
870/// Indicates the manner in which a thread exited.
871///
872/// A thread that completes without panicking is considered to exit successfully.
85aaf69f
SL
873#[stable(feature = "rust1", since = "1.0.0")]
874pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
1a4d82fc 875
d9579d0f
AL
876// This packet is used to communicate the return value between the child thread
877// and the parent thread. Memory is shared through the `Arc` within and there's
878// no need for a mutex here because synchronization happens with `join()` (the
879// parent thread never reads this packet until the child has exited).
880//
881// This packet itself is then stored into a `JoinInner` which in turns is placed
882// in `JoinHandle` and `JoinGuard`. Due to the usage of `UnsafeCell` we need to
883// manually worry about impls like Send and Sync. The type `T` should
884// already always be Send (otherwise the thread could not have been created) and
885// this type is inherently Sync because no methods take &self. Regardless,
886// however, we add inheriting impls for Send/Sync to this type to ensure it's
887// Send/Sync and that future modifications will still appropriately classify it.
1a4d82fc
JJ
888struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
889
d9579d0f
AL
890unsafe impl<T: Send> Send for Packet<T> {}
891unsafe impl<T: Sync> Sync for Packet<T> {}
1a4d82fc 892
e9174d1e 893/// Inner representation for JoinHandle
85aaf69f 894struct JoinInner<T> {
d9579d0f 895 native: Option<imp::Thread>,
85aaf69f
SL
896 thread: Thread,
897 packet: Packet<T>,
85aaf69f
SL
898}
899
900impl<T> JoinInner<T> {
901 fn join(&mut self) -> Result<T> {
d9579d0f 902 self.native.take().unwrap().join();
85aaf69f
SL
903 unsafe {
904 (*self.packet.0.get()).take().unwrap()
905 }
906 }
907}
908
909/// An owned permission to join on a thread (block on its termination).
910///
e9174d1e 911/// A `JoinHandle` *detaches* the child thread when it is dropped.
85aaf69f 912///
32a655c1 913/// Due to platform restrictions, it is not possible to [`Clone`] this
85aaf69f
SL
914/// handle: the ability to join a child thread is a uniquely-owned
915/// permission.
3157f602
XL
916///
917/// This `struct` is created by the [`thread::spawn`] function and the
918/// [`thread::Builder::spawn`] method.
919///
920/// # Examples
921///
922/// Creation from [`thread::spawn`]:
923///
32a655c1 924/// ```
3157f602
XL
925/// use std::thread;
926///
927/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| {
928/// // some work here
929/// });
930/// ```
931///
932/// Creation from [`thread::Builder::spawn`]:
933///
32a655c1 934/// ```
3157f602
XL
935/// use std::thread;
936///
937/// let builder = thread::Builder::new();
938///
939/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
940/// // some work here
941/// }).unwrap();
942/// ```
943///
32a655c1 944/// [`Clone`]: ../../std/clone/trait.Clone.html
3157f602
XL
945/// [`thread::spawn`]: fn.spawn.html
946/// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn
85aaf69f 947#[stable(feature = "rust1", since = "1.0.0")]
9346a6ac 948pub struct JoinHandle<T>(JoinInner<T>);
85aaf69f 949
9346a6ac 950impl<T> JoinHandle<T> {
32a655c1
SL
951 /// Extracts a handle to the underlying thread.
952 ///
953 /// # Examples
954 ///
955 /// ```
956 /// #![feature(thread_id)]
957 ///
958 /// use std::thread;
959 ///
960 /// let builder = thread::Builder::new();
961 ///
962 /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
963 /// // some work here
964 /// }).unwrap();
965 ///
966 /// let thread = join_handle.thread();
967 /// println!("thread id: {:?}", thread.id());
968 /// ```
85aaf69f
SL
969 #[stable(feature = "rust1", since = "1.0.0")]
970 pub fn thread(&self) -> &Thread {
971 &self.0.thread
972 }
973
9346a6ac 974 /// Waits for the associated thread to finish.
85aaf69f 975 ///
32a655c1
SL
976 /// If the child thread panics, [`Err`] is returned with the parameter given
977 /// to [`panic`].
978 ///
979 /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
980 /// [`panic`]: ../../std/macro.panic.html
981 ///
982 /// # Examples
983 ///
984 /// ```
985 /// use std::thread;
986 ///
987 /// let builder = thread::Builder::new();
988 ///
989 /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
990 /// // some work here
991 /// }).unwrap();
992 /// join_handle.join().expect("Couldn't join on the associated thread");
993 /// ```
85aaf69f 994 #[stable(feature = "rust1", since = "1.0.0")]
9346a6ac 995 pub fn join(mut self) -> Result<T> {
85aaf69f
SL
996 self.0.join()
997 }
998}
999
92a42be0
SL
1000impl<T> AsInner<imp::Thread> for JoinHandle<T> {
1001 fn as_inner(&self) -> &imp::Thread { self.0.native.as_ref().unwrap() }
1002}
1003
1004impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
1005 fn into_inner(self) -> imp::Thread { self.0.native.unwrap() }
1006}
1007
8bb4bdeb 1008#[stable(feature = "std_debug", since = "1.16.0")]
32a655c1
SL
1009impl<T> fmt::Debug for JoinHandle<T> {
1010 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1011 f.pad("JoinHandle { .. }")
1012 }
1013}
1014
d9579d0f
AL
1015fn _assert_sync_and_send() {
1016 fn _assert_both<T: Send + Sync>() {}
1017 _assert_both::<JoinHandle<()>>();
d9579d0f
AL
1018 _assert_both::<Thread>();
1019}
1020
c34b1796
AL
1021////////////////////////////////////////////////////////////////////////////////
1022// Tests
1023////////////////////////////////////////////////////////////////////////////////
1024
c30ab7b3 1025#[cfg(all(test, not(target_os = "emscripten")))]
d9579d0f 1026mod tests {
1a4d82fc
JJ
1027 use any::Any;
1028 use sync::mpsc::{channel, Sender};
1a4d82fc 1029 use result;
c34b1796 1030 use super::{Builder};
85aaf69f 1031 use thread;
85aaf69f 1032 use time::Duration;
c34b1796 1033 use u32;
1a4d82fc
JJ
1034
1035 // !!! These tests are dangerous. If something is buggy, they will hang, !!!
1036 // !!! instead of exiting cleanly. This might wedge the buildbots. !!!
1037
1038 #[test]
1039 fn test_unnamed_thread() {
85aaf69f
SL
1040 thread::spawn(move|| {
1041 assert!(thread::current().name().is_none());
1042 }).join().ok().unwrap();
1a4d82fc
JJ
1043 }
1044
1045 #[test]
1046 fn test_named_thread() {
e9174d1e 1047 Builder::new().name("ada lovelace".to_string()).spawn(move|| {
85aaf69f 1048 assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
e9174d1e 1049 }).unwrap().join().unwrap();
1a4d82fc
JJ
1050 }
1051
54a0048b
SL
1052 #[test]
1053 #[should_panic]
1054 fn test_invalid_named_thread() {
1055 let _ = Builder::new().name("ada l\0velace".to_string()).spawn(|| {});
1056 }
1057
1a4d82fc
JJ
1058 #[test]
1059 fn test_run_basic() {
1060 let (tx, rx) = channel();
85aaf69f 1061 thread::spawn(move|| {
1a4d82fc
JJ
1062 tx.send(()).unwrap();
1063 });
1064 rx.recv().unwrap();
1065 }
1066
1a4d82fc
JJ
1067 #[test]
1068 fn test_join_panic() {
85aaf69f 1069 match thread::spawn(move|| {
1a4d82fc
JJ
1070 panic!()
1071 }).join() {
1072 result::Result::Err(_) => (),
1073 result::Result::Ok(()) => panic!()
1074 }
1075 }
1076
1077 #[test]
1078 fn test_spawn_sched() {
1a4d82fc
JJ
1079 let (tx, rx) = channel();
1080
c34b1796 1081 fn f(i: i32, tx: Sender<()>) {
1a4d82fc 1082 let tx = tx.clone();
85aaf69f 1083 thread::spawn(move|| {
1a4d82fc
JJ
1084 if i == 0 {
1085 tx.send(()).unwrap();
1086 } else {
1087 f(i - 1, tx);
1088 }
1089 });
1090
1091 }
1092 f(10, tx);
1093 rx.recv().unwrap();
1094 }
1095
1096 #[test]
1097 fn test_spawn_sched_childs_on_default_sched() {
1098 let (tx, rx) = channel();
1099
85aaf69f
SL
1100 thread::spawn(move|| {
1101 thread::spawn(move|| {
1a4d82fc
JJ
1102 tx.send(()).unwrap();
1103 });
1104 });
1105
1106 rx.recv().unwrap();
1107 }
1108
e9174d1e 1109 fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<Fn() + Send>) {
c34b1796 1110 let (tx, rx) = channel();
1a4d82fc 1111
c34b1796
AL
1112 let x: Box<_> = box 1;
1113 let x_in_parent = (&*x) as *const i32 as usize;
1a4d82fc 1114
c34b1796
AL
1115 spawnfn(Box::new(move|| {
1116 let x_in_child = (&*x) as *const i32 as usize;
1a4d82fc
JJ
1117 tx.send(x_in_child).unwrap();
1118 }));
1119
1120 let x_in_child = rx.recv().unwrap();
1121 assert_eq!(x_in_parent, x_in_child);
1122 }
1123
1124 #[test]
1125 fn test_avoid_copying_the_body_spawn() {
1126 avoid_copying_the_body(|v| {
c34b1796 1127 thread::spawn(move || v());
1a4d82fc
JJ
1128 });
1129 }
1130
1131 #[test]
1132 fn test_avoid_copying_the_body_thread_spawn() {
1133 avoid_copying_the_body(|f| {
85aaf69f 1134 thread::spawn(move|| {
c34b1796 1135 f();
1a4d82fc
JJ
1136 });
1137 })
1138 }
1139
1140 #[test]
1141 fn test_avoid_copying_the_body_join() {
1142 avoid_copying_the_body(|f| {
85aaf69f 1143 let _ = thread::spawn(move|| {
c34b1796 1144 f()
1a4d82fc
JJ
1145 }).join();
1146 })
1147 }
1148
1149 #[test]
1150 fn test_child_doesnt_ref_parent() {
bd371182
AL
1151 // If the child refcounts the parent thread, this will stack overflow when
1152 // climbing the thread tree to dereference each ancestor. (See #1789)
1a4d82fc
JJ
1153 // (well, it would if the constant were 8000+ - I lowered it to be more
1154 // valgrind-friendly. try this at home, instead..!)
c34b1796 1155 const GENERATIONS: u32 = 16;
e9174d1e 1156 fn child_no(x: u32) -> Box<Fn() + Send> {
c34b1796 1157 return Box::new(move|| {
1a4d82fc 1158 if x < GENERATIONS {
c34b1796 1159 thread::spawn(move|| child_no(x+1)());
1a4d82fc
JJ
1160 }
1161 });
1162 }
c34b1796 1163 thread::spawn(|| child_no(0)());
1a4d82fc
JJ
1164 }
1165
1166 #[test]
1167 fn test_simple_newsched_spawn() {
85aaf69f 1168 thread::spawn(move || {});
1a4d82fc
JJ
1169 }
1170
1171 #[test]
1172 fn test_try_panic_message_static_str() {
85aaf69f 1173 match thread::spawn(move|| {
1a4d82fc
JJ
1174 panic!("static string");
1175 }).join() {
1176 Err(e) => {
1177 type T = &'static str;
1178 assert!(e.is::<T>());
c34b1796 1179 assert_eq!(*e.downcast::<T>().unwrap(), "static string");
1a4d82fc
JJ
1180 }
1181 Ok(()) => panic!()
1182 }
1183 }
1184
1185 #[test]
1186 fn test_try_panic_message_owned_str() {
85aaf69f 1187 match thread::spawn(move|| {
1a4d82fc
JJ
1188 panic!("owned string".to_string());
1189 }).join() {
1190 Err(e) => {
1191 type T = String;
1192 assert!(e.is::<T>());
c34b1796 1193 assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
1a4d82fc
JJ
1194 }
1195 Ok(()) => panic!()
1196 }
1197 }
1198
1199 #[test]
1200 fn test_try_panic_message_any() {
85aaf69f 1201 match thread::spawn(move|| {
1a4d82fc
JJ
1202 panic!(box 413u16 as Box<Any + Send>);
1203 }).join() {
1204 Err(e) => {
1205 type T = Box<Any + Send>;
1206 assert!(e.is::<T>());
c34b1796 1207 let any = e.downcast::<T>().unwrap();
1a4d82fc 1208 assert!(any.is::<u16>());
c34b1796 1209 assert_eq!(*any.downcast::<u16>().unwrap(), 413);
1a4d82fc
JJ
1210 }
1211 Ok(()) => panic!()
1212 }
1213 }
1214
1215 #[test]
1216 fn test_try_panic_message_unit_struct() {
1217 struct Juju;
1218
85aaf69f 1219 match thread::spawn(move|| {
1a4d82fc
JJ
1220 panic!(Juju)
1221 }).join() {
1222 Err(ref e) if e.is::<Juju>() => {}
1223 Err(_) | Ok(()) => panic!()
1224 }
1225 }
1226
85aaf69f
SL
1227 #[test]
1228 fn test_park_timeout_unpark_before() {
1229 for _ in 0..10 {
1230 thread::current().unpark();
9cc50fc6 1231 thread::park_timeout(Duration::from_millis(u32::MAX as u64));
85aaf69f
SL
1232 }
1233 }
1234
1235 #[test]
1236 fn test_park_timeout_unpark_not_called() {
1237 for _ in 0..10 {
9cc50fc6 1238 thread::park_timeout(Duration::from_millis(10));
85aaf69f
SL
1239 }
1240 }
1241
1242 #[test]
1243 fn test_park_timeout_unpark_called_other_thread() {
85aaf69f
SL
1244 for _ in 0..10 {
1245 let th = thread::current();
1246
1247 let _guard = thread::spawn(move || {
9cc50fc6 1248 super::sleep(Duration::from_millis(50));
85aaf69f
SL
1249 th.unpark();
1250 });
1251
9cc50fc6 1252 thread::park_timeout(Duration::from_millis(u32::MAX as u64));
85aaf69f
SL
1253 }
1254 }
1255
c34b1796
AL
1256 #[test]
1257 fn sleep_ms_smoke() {
9cc50fc6 1258 thread::sleep(Duration::from_millis(2));
c34b1796
AL
1259 }
1260
c30ab7b3
SL
1261 #[test]
1262 fn test_thread_id_equal() {
1263 assert!(thread::current().id() == thread::current().id());
1264 }
1265
1266 #[test]
1267 fn test_thread_id_not_equal() {
1268 let spawned_id = thread::spawn(|| thread::current().id()).join().unwrap();
1269 assert!(thread::current().id() != spawned_id);
1270 }
1271
bd371182 1272 // NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due
1a4d82fc
JJ
1273 // to the test harness apparently interfering with stderr configuration.
1274}