]> git.proxmox.com Git - rustc.git/blame - src/libstd/thread/mod.rs
New upstream version 1.12.0+dfsg1
[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
20//! [channels](../../std/sync/mpsc/index.html), Rust's message-passing
21//! types, along with [other forms of thread
22//! synchronization](../../std/sync/index.html) and shared-memory data
23//! structures. In particular, types that are guaranteed to be
24//! threadsafe are easily shared between threads using the
25//! atomically-reference-counted container,
26//! [`Arc`](../../std/sync/struct.Arc.html).
27//!
28//! Fatal logic errors in Rust cause *thread panic*, during which
29//! a thread will unwind the stack, running destructors and freeing
30//! owned resources. Thread panic is unrecoverable from within
31//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
c34b1796
AL
32//! the panic may optionally be detected from a different thread. If
33//! the main thread panics, the application will exit with a non-zero
1a4d82fc
JJ
34//! exit code.
35//!
36//! When the main thread of a Rust program terminates, the entire program shuts
37//! down, even if other threads are still running. However, this module provides
38//! convenient facilities for automatically waiting for the termination of a
c34b1796 39//! child thread (i.e., join).
1a4d82fc 40//!
1a4d82fc
JJ
41//! ## Spawning a thread
42//!
85aaf69f 43//! A new thread can be spawned using the `thread::spawn` function:
1a4d82fc
JJ
44//!
45//! ```rust
85aaf69f 46//! use std::thread;
1a4d82fc 47//!
85aaf69f 48//! thread::spawn(move || {
c34b1796 49//! // some work here
1a4d82fc
JJ
50//! });
51//! ```
52//!
85aaf69f 53//! In this example, the spawned thread is "detached" from the current
c34b1796
AL
54//! thread. This means that it can outlive its parent (the thread that spawned
55//! it), unless this parent is the main thread.
1a4d82fc 56//!
9346a6ac
AL
57//! The parent thread can also wait on the completion of the child
58//! thread; a call to `spawn` produces a `JoinHandle`, which provides
59//! a `join` method for waiting:
60//!
61//! ```rust
62//! use std::thread;
63//!
64//! let child = thread::spawn(move || {
65//! // some work here
66//! });
67//! // some work here
68//! let res = child.join();
69//! ```
70//!
71//! The `join` method returns a `Result` containing `Ok` of the final
72//! value produced by the child thread, or `Err` of the value given to
73//! a call to `panic!` if the child panicked.
74//!
1a4d82fc
JJ
75//! ## Configuring threads
76//!
77//! A new thread can be configured before it is spawned via the `Builder` type,
bd371182 78//! which currently allows you to set the name and stack size for the child thread:
1a4d82fc
JJ
79//!
80//! ```rust
9346a6ac 81//! # #![allow(unused_must_use)]
1a4d82fc
JJ
82//! use std::thread;
83//!
84//! thread::Builder::new().name("child1".to_string()).spawn(move || {
c34b1796 85//! println!("Hello, world!");
1a4d82fc
JJ
86//! });
87//! ```
88//!
a7813a04
XL
89//! ## The `Thread` type
90//!
91//! Threads are represented via the `Thread` type, which you can get in one of
92//! two ways:
93//!
94//! * By spawning a new thread, e.g. using the `thread::spawn` function, and
95//! calling `thread()` on the `JoinHandle`.
96//! * By requesting the current thread, using the `thread::current` function.
97//!
98//! The `thread::current()` function is available even for threads not spawned
99//! by the APIs of this module.
100//!
1a4d82fc
JJ
101//! ## Blocking support: park and unpark
102//!
103//! Every thread is equipped with some basic low-level blocking support, via the
a7813a04
XL
104//! `thread::park()` function and `thread::Thread::unpark()` method. `park()`
105//! blocks the current thread, which can then be resumed from another thread by
106//! calling the `unpark()` method on the blocked thread's handle.
1a4d82fc
JJ
107//!
108//! Conceptually, each `Thread` handle has an associated token, which is
109//! initially not present:
110//!
85aaf69f 111//! * The `thread::park()` function blocks the current thread unless or until
c34b1796 112//! the token is available for its thread handle, at which point it atomically
1a4d82fc 113//! consumes the token. It may also return *spuriously*, without consuming the
85aaf69f
SL
114//! token. `thread::park_timeout()` does the same, but allows specifying a
115//! maximum time to block the thread for.
1a4d82fc
JJ
116//!
117//! * The `unpark()` method on a `Thread` atomically makes the token available
118//! if it wasn't already.
119//!
120//! In other words, each `Thread` acts a bit like a semaphore with initial count
121//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
122//! and can return spuriously.
123//!
124//! The API is typically used by acquiring a handle to the current thread,
125//! placing that handle in a shared data structure so that other threads can
126//! find it, and then `park`ing. When some desired condition is met, another
127//! thread calls `unpark` on the handle.
128//!
129//! The motivation for this design is twofold:
130//!
131//! * It avoids the need to allocate mutexes and condvars when building new
132//! synchronization primitives; the threads already provide basic blocking/signaling.
133//!
c34b1796
AL
134//! * It can be implemented very efficiently on many platforms.
135//!
136//! ## Thread-local storage
137//!
138//! This module also provides an implementation of thread local storage for Rust
139//! programs. Thread local storage is a method of storing data into a global
140//! variable which each thread in the program will have its own copy of.
141//! Threads do not share this data, so accesses do not need to be synchronized.
142//!
143//! At a high level, this module provides two variants of storage:
144//!
145//! * Owned thread-local storage. This is a type of thread local key which
146//! owns the value that it contains, and will destroy the value when the
147//! thread exits. This variant is created with the `thread_local!` macro and
148//! can contain any value which is `'static` (no borrowed pointers).
149//!
150//! * Scoped thread-local storage. This type of key is used to store a reference
151//! to a value into local storage temporarily for the scope of a function
152//! call. There are no restrictions on what types of values can be placed
153//! into this key.
154//!
155//! Both forms of thread local storage provide an accessor function, `with`,
156//! which will yield a shared reference to the value to the specified
157//! closure. Thread-local keys only allow shared access to values as there is no
158//! way to guarantee uniqueness if a mutable borrow was allowed. Most values
159//! will want to make use of some form of **interior mutability** through the
160//! `Cell` or `RefCell` types.
1a4d82fc 161
85aaf69f
SL
162#![stable(feature = "rust1", since = "1.0.0")]
163
164use prelude::v1::*;
1a4d82fc
JJ
165
166use any::Any;
1a4d82fc 167use cell::UnsafeCell;
a7813a04 168use ffi::{CStr, CString};
85aaf69f
SL
169use fmt;
170use io;
a7813a04
XL
171use panic;
172use panicking;
54a0048b 173use str;
85aaf69f 174use sync::{Mutex, Condvar, Arc};
c34b1796 175use sys::thread as imp;
e9174d1e 176use sys_common::thread_info;
e9174d1e 177use sys_common::util;
92a42be0 178use sys_common::{AsInner, IntoInner};
85aaf69f 179use time::Duration;
1a4d82fc 180
c34b1796
AL
181////////////////////////////////////////////////////////////////////////////////
182// Thread-local storage
183////////////////////////////////////////////////////////////////////////////////
184
9346a6ac 185#[macro_use] mod local;
9346a6ac
AL
186
187#[stable(feature = "rust1", since = "1.0.0")]
188pub use self::local::{LocalKey, LocalKeyState};
189
92a42be0 190#[unstable(feature = "libstd_thread_internals", issue = "0")]
9cc50fc6
SL
191#[cfg(target_thread_local)]
192#[doc(hidden)] pub use self::local::elf::Key as __ElfLocalKeyInner;
193#[unstable(feature = "libstd_thread_internals", issue = "0")]
194#[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
c34b1796
AL
195
196////////////////////////////////////////////////////////////////////////////////
197// Builder
198////////////////////////////////////////////////////////////////////////////////
1a4d82fc
JJ
199
200/// Thread configuration. Provides detailed control over the properties
201/// and behavior of new threads.
85aaf69f 202#[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
203pub struct Builder {
204 // A name for the thread-to-be, for identification in panic messages
205 name: Option<String>,
206 // The size of the stack for the spawned thread
c34b1796 207 stack_size: Option<usize>,
1a4d82fc
JJ
208}
209
210impl Builder {
9346a6ac 211 /// Generates the base configuration for spawning a thread, from which
1a4d82fc 212 /// configuration methods can be chained.
85aaf69f 213 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
214 pub fn new() -> Builder {
215 Builder {
216 name: None,
217 stack_size: None,
1a4d82fc
JJ
218 }
219 }
220
9346a6ac 221 /// Names the thread-to-be. Currently the name is used for identification
1a4d82fc 222 /// only in panic messages.
3157f602
XL
223 ///
224 /// # Examples
225 ///
226 /// ```rust
227 /// use std::thread;
228 ///
229 /// let builder = thread::Builder::new()
230 /// .name("foo".into());
231 ///
232 /// let handler = builder.spawn(|| {
233 /// assert_eq!(thread::current().name(), Some("foo"))
234 /// }).unwrap();
235 ///
236 /// handler.join().unwrap();
237 /// ```
85aaf69f 238 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
239 pub fn name(mut self, name: String) -> Builder {
240 self.name = Some(name);
241 self
242 }
243
9346a6ac 244 /// Sets the size of the stack for the new thread.
85aaf69f 245 #[stable(feature = "rust1", since = "1.0.0")]
c34b1796 246 pub fn stack_size(mut self, size: usize) -> Builder {
1a4d82fc
JJ
247 self.stack_size = Some(size);
248 self
249 }
250
9346a6ac 251 /// Spawns a new thread, and returns a join handle for it.
1a4d82fc 252 ///
85aaf69f
SL
253 /// The child thread may outlive the parent (unless the parent thread
254 /// is the main thread; the whole process is terminated when the main
bd371182 255 /// thread finishes). The join handle can be used to block on
85aaf69f
SL
256 /// termination of the child thread, including recovering its panics.
257 ///
258 /// # Errors
259 ///
260 /// Unlike the `spawn` free function, this method yields an
261 /// `io::Result` to capture any failure to create the thread at
262 /// the OS level.
263 #[stable(feature = "rust1", since = "1.0.0")]
9346a6ac
AL
264 pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
265 F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
85aaf69f 266 {
c34b1796 267 let Builder { name, stack_size } = self;
1a4d82fc 268
e9174d1e 269 let stack_size = stack_size.unwrap_or(util::min_stack());
85aaf69f 270
1a4d82fc
JJ
271 let my_thread = Thread::new(name);
272 let their_thread = my_thread.clone();
273
b039eaaf
SL
274 let my_packet : Arc<UnsafeCell<Option<Result<T>>>>
275 = Arc::new(UnsafeCell::new(None));
d9579d0f 276 let their_packet = my_packet.clone();
85aaf69f 277
85aaf69f 278 let main = move || {
54a0048b 279 if let Some(name) = their_thread.cname() {
d9579d0f 280 imp::Thread::set_name(name);
85aaf69f 281 }
b039eaaf
SL
282 unsafe {
283 thread_info::set(imp::guard::current(), their_thread);
a7813a04
XL
284 let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
285 *their_packet.get() = Some(try_result);
b039eaaf 286 }
1a4d82fc
JJ
287 };
288
b039eaaf
SL
289 Ok(JoinHandle(JoinInner {
290 native: unsafe {
54a0048b 291 Some(imp::Thread::new(stack_size, Box::new(main))?)
b039eaaf 292 },
85aaf69f 293 thread: my_thread,
d9579d0f 294 packet: Packet(my_packet),
b039eaaf 295 }))
1a4d82fc
JJ
296 }
297}
298
c34b1796
AL
299////////////////////////////////////////////////////////////////////////////////
300// Free functions
301////////////////////////////////////////////////////////////////////////////////
302
9346a6ac 303/// Spawns a new thread, returning a `JoinHandle` for it.
85aaf69f 304///
c34b1796
AL
305/// The join handle will implicitly *detach* the child thread upon being
306/// dropped. In this case, the child thread may outlive the parent (unless
307/// the parent thread is the main thread; the whole process is terminated when
308/// the main thread finishes.) Additionally, the join handle provides a `join`
309/// method that can be used to join the child thread. If the child thread
310/// panics, `join` will return an `Err` containing the argument given to
311/// `panic`.
85aaf69f
SL
312///
313/// # Panics
314///
9346a6ac 315/// Panics if the OS fails to create a thread; use `Builder::spawn`
85aaf69f
SL
316/// to recover from such errors.
317#[stable(feature = "rust1", since = "1.0.0")]
9346a6ac
AL
318pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
319 F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
320{
85aaf69f
SL
321 Builder::new().spawn(f).unwrap()
322}
323
85aaf69f
SL
324/// Gets a handle to the thread that invokes it.
325#[stable(feature = "rust1", since = "1.0.0")]
326pub fn current() -> Thread {
d9579d0f
AL
327 thread_info::current_thread().expect("use of std::thread::current() is not \
328 possible after the thread's local \
329 data has been destroyed")
85aaf69f
SL
330}
331
9346a6ac 332/// Cooperatively gives up a timeslice to the OS scheduler.
85aaf69f
SL
333#[stable(feature = "rust1", since = "1.0.0")]
334pub fn yield_now() {
d9579d0f 335 imp::Thread::yield_now()
85aaf69f
SL
336}
337
338/// Determines whether the current thread is unwinding because of panic.
3157f602
XL
339///
340/// # Examples
341///
342/// ```rust,should_panic
343/// use std::thread;
344///
345/// struct SomeStruct;
346///
347/// impl Drop for SomeStruct {
348/// fn drop(&mut self) {
349/// if thread::panicking() {
350/// println!("dropped while unwinding");
351/// } else {
352/// println!("dropped while not unwinding");
353/// }
354/// }
355/// }
356///
357/// {
358/// print!("a: ");
359/// let a = SomeStruct;
360/// }
361///
362/// {
363/// print!("b: ");
364/// let b = SomeStruct;
365/// panic!()
366/// }
367/// ```
85aaf69f
SL
368#[inline]
369#[stable(feature = "rust1", since = "1.0.0")]
370pub fn panicking() -> bool {
a7813a04 371 panicking::panicking()
85aaf69f
SL
372}
373
9346a6ac 374/// Puts the current thread to sleep for the specified amount of time.
c34b1796
AL
375///
376/// The thread may sleep longer than the duration specified due to scheduling
377/// specifics or platform-dependent functionality. Note that on unix platforms
378/// this function will not return early due to a signal being received or a
379/// spurious wakeup.
380#[stable(feature = "rust1", since = "1.0.0")]
92a42be0 381#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::sleep`")]
c34b1796 382pub fn sleep_ms(ms: u32) {
d9579d0f
AL
383 sleep(Duration::from_millis(ms as u64))
384}
385
386/// Puts the current thread to sleep for the specified amount of time.
387///
388/// The thread may sleep longer than the duration specified due to scheduling
389/// specifics or platform-dependent functionality.
390///
391/// # Platform behavior
392///
393/// On Unix platforms this function will not return early due to a
394/// signal being received or a spurious wakeup. Platforms which do not support
395/// nanosecond precision for sleeping will have `dur` rounded up to the nearest
396/// granularity of time they can sleep for.
3157f602
XL
397///
398/// # Examples
399///
400/// ```rust,no_run
401/// use std::{thread, time};
402///
403/// let ten_millis = time::Duration::from_millis(10);
404/// let now = time::Instant::now();
405///
406/// thread::sleep(ten_millis);
407///
408/// assert!(now.elapsed() >= ten_millis);
409/// ```
e9174d1e 410#[stable(feature = "thread_sleep", since = "1.4.0")]
d9579d0f
AL
411pub fn sleep(dur: Duration) {
412 imp::Thread::sleep(dur)
c34b1796
AL
413}
414
c1a9b12d
SL
415/// Blocks unless or until the current thread's token is made available.
416///
417/// Every thread is equipped with some basic low-level blocking support, via
418/// the `park()` function and the [`unpark()`][unpark] method. These can be
419/// used as a more CPU-efficient implementation of a spinlock.
420///
421/// [unpark]: struct.Thread.html#method.unpark
422///
423/// The API is typically used by acquiring a handle to the current thread,
424/// placing that handle in a shared data structure so that other threads can
425/// find it, and then parking (in a loop with a check for the token actually
426/// being acquired).
427///
428/// A call to `park` does not guarantee that the thread will remain parked
429/// forever, and callers should be prepared for this possibility.
430///
431/// See the [module documentation][thread] for more detail.
85aaf69f 432///
c1a9b12d 433/// [thread]: index.html
85aaf69f
SL
434//
435// The implementation currently uses the trivial strategy of a Mutex+Condvar
436// with wakeup flag, which does not actually allow spurious wakeups. In the
437// future, this will be implemented in a more efficient way, perhaps along the lines of
438// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
439// or futuxes, and in either case may allow spurious wakeups.
440#[stable(feature = "rust1", since = "1.0.0")]
441pub fn park() {
442 let thread = current();
443 let mut guard = thread.inner.lock.lock().unwrap();
444 while !*guard {
445 guard = thread.inner.cvar.wait(guard).unwrap();
446 }
447 *guard = false;
448}
449
5bcae85e
SL
450/// Use [park_timeout].
451///
9346a6ac 452/// Blocks unless or until the current thread's token is made available or
85aaf69f
SL
453/// the specified duration has been reached (may wake spuriously).
454///
455/// The semantics of this function are equivalent to `park()` except that the
3157f602 456/// thread will be blocked for roughly no longer than `ms`. This method
85aaf69f
SL
457/// should not be used for precise timing due to anomalies such as
458/// preemption or platform differences that may not cause the maximum
3157f602 459/// amount of time waited to be precisely `ms` long.
85aaf69f 460///
5bcae85e
SL
461/// See the [module documentation][thread] for more detail.
462///
463/// [thread]: index.html
464/// [park_timeout]: fn.park_timeout.html
c34b1796 465#[stable(feature = "rust1", since = "1.0.0")]
92a42be0 466#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")]
c34b1796 467pub fn park_timeout_ms(ms: u32) {
d9579d0f
AL
468 park_timeout(Duration::from_millis(ms as u64))
469}
470
471/// Blocks unless or until the current thread's token is made available or
472/// the specified duration has been reached (may wake spuriously).
473///
474/// The semantics of this function are equivalent to `park()` except that the
3157f602 475/// thread will be blocked for roughly no longer than `dur`. This method
d9579d0f
AL
476/// should not be used for precise timing due to anomalies such as
477/// preemption or platform differences that may not cause the maximum
3157f602 478/// amount of time waited to be precisely `dur` long.
d9579d0f
AL
479///
480/// See the module doc for more detail.
481///
482/// # Platform behavior
483///
484/// Platforms which do not support nanosecond precision for sleeping will have
485/// `dur` rounded up to the nearest granularity of time they can sleep for.
5bcae85e
SL
486///
487/// # Example
488///
489/// Waiting for the complete expiration of the timeout:
490///
491/// ```rust,no_run
492/// use std::thread::park_timeout;
493/// use std::time::{Instant, Duration};
494///
495/// let timeout = Duration::from_secs(2);
496/// let beginning_park = Instant::now();
497/// park_timeout(timeout);
498///
499/// while beginning_park.elapsed() < timeout {
500/// println!("restarting park_timeout after {:?}", beginning_park.elapsed());
501/// let timeout = timeout - beginning_park.elapsed();
502/// park_timeout(timeout);
503/// }
504/// ```
e9174d1e 505#[stable(feature = "park_timeout", since = "1.4.0")]
d9579d0f 506pub fn park_timeout(dur: Duration) {
85aaf69f
SL
507 let thread = current();
508 let mut guard = thread.inner.lock.lock().unwrap();
509 if !*guard {
d9579d0f 510 let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
85aaf69f
SL
511 guard = g;
512 }
513 *guard = false;
514}
515
c34b1796
AL
516////////////////////////////////////////////////////////////////////////////////
517// Thread
518////////////////////////////////////////////////////////////////////////////////
519
85aaf69f 520/// The internal representation of a `Thread` handle
1a4d82fc 521struct Inner {
54a0048b 522 name: Option<CString>, // Guaranteed to be UTF-8
1a4d82fc
JJ
523 lock: Mutex<bool>, // true when there is a buffered unpark
524 cvar: Condvar,
525}
526
1a4d82fc 527#[derive(Clone)]
85aaf69f 528#[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
529/// A handle to a thread.
530pub struct Thread {
531 inner: Arc<Inner>,
532}
533
534impl Thread {
535 // Used only internally to construct a thread object without spawning
536 fn new(name: Option<String>) -> Thread {
3157f602
XL
537 let cname = name.map(|n| {
538 CString::new(n).expect("thread name may not contain interior null bytes")
539 });
1a4d82fc
JJ
540 Thread {
541 inner: Arc::new(Inner {
54a0048b 542 name: cname,
1a4d82fc
JJ
543 lock: Mutex::new(false),
544 cvar: Condvar::new(),
545 })
546 }
547 }
548
1a4d82fc
JJ
549 /// Atomically makes the handle's token available if it is not already.
550 ///
551 /// See the module doc for more detail.
85aaf69f 552 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc
JJ
553 pub fn unpark(&self) {
554 let mut guard = self.inner.lock.lock().unwrap();
555 if !*guard {
556 *guard = true;
557 self.inner.cvar.notify_one();
558 }
559 }
560
9346a6ac 561 /// Gets the thread's name.
3157f602
XL
562 ///
563 /// # Examples
564 ///
565 /// Threads by default have no name specified:
566 ///
567 /// ```
568 /// use std::thread;
569 ///
570 /// let builder = thread::Builder::new();
571 ///
572 /// let handler = builder.spawn(|| {
573 /// assert!(thread::current().name().is_none());
574 /// }).unwrap();
575 ///
576 /// handler.join().unwrap();
577 /// ```
578 ///
579 /// Thread with a specified name:
580 ///
581 /// ```
582 /// use std::thread;
583 ///
584 /// let builder = thread::Builder::new()
585 /// .name("foo".into());
586 ///
587 /// let handler = builder.spawn(|| {
588 /// assert_eq!(thread::current().name(), Some("foo"))
589 /// }).unwrap();
590 ///
591 /// handler.join().unwrap();
592 /// ```
85aaf69f 593 #[stable(feature = "rust1", since = "1.0.0")]
1a4d82fc 594 pub fn name(&self) -> Option<&str> {
54a0048b
SL
595 self.cname().map(|s| unsafe { str::from_utf8_unchecked(s.to_bytes()) } )
596 }
597
598 fn cname(&self) -> Option<&CStr> {
85aaf69f
SL
599 self.inner.name.as_ref().map(|s| &**s)
600 }
601}
602
603#[stable(feature = "rust1", since = "1.0.0")]
604impl fmt::Debug for Thread {
605 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
606 fmt::Debug::fmt(&self.name(), f)
1a4d82fc
JJ
607 }
608}
609
610// a hack to get around privacy restrictions
611impl thread_info::NewThread for Thread {
612 fn new(name: Option<String>) -> Thread { Thread::new(name) }
613}
614
c34b1796 615////////////////////////////////////////////////////////////////////////////////
e9174d1e 616// JoinHandle
c34b1796
AL
617////////////////////////////////////////////////////////////////////////////////
618
1a4d82fc
JJ
619/// Indicates the manner in which a thread exited.
620///
621/// A thread that completes without panicking is considered to exit successfully.
85aaf69f
SL
622#[stable(feature = "rust1", since = "1.0.0")]
623pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
1a4d82fc 624
d9579d0f
AL
625// This packet is used to communicate the return value between the child thread
626// and the parent thread. Memory is shared through the `Arc` within and there's
627// no need for a mutex here because synchronization happens with `join()` (the
628// parent thread never reads this packet until the child has exited).
629//
630// This packet itself is then stored into a `JoinInner` which in turns is placed
631// in `JoinHandle` and `JoinGuard`. Due to the usage of `UnsafeCell` we need to
632// manually worry about impls like Send and Sync. The type `T` should
633// already always be Send (otherwise the thread could not have been created) and
634// this type is inherently Sync because no methods take &self. Regardless,
635// however, we add inheriting impls for Send/Sync to this type to ensure it's
636// Send/Sync and that future modifications will still appropriately classify it.
1a4d82fc
JJ
637struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
638
d9579d0f
AL
639unsafe impl<T: Send> Send for Packet<T> {}
640unsafe impl<T: Sync> Sync for Packet<T> {}
1a4d82fc 641
e9174d1e 642/// Inner representation for JoinHandle
85aaf69f 643struct JoinInner<T> {
d9579d0f 644 native: Option<imp::Thread>,
85aaf69f
SL
645 thread: Thread,
646 packet: Packet<T>,
85aaf69f
SL
647}
648
649impl<T> JoinInner<T> {
650 fn join(&mut self) -> Result<T> {
d9579d0f 651 self.native.take().unwrap().join();
85aaf69f
SL
652 unsafe {
653 (*self.packet.0.get()).take().unwrap()
654 }
655 }
656}
657
658/// An owned permission to join on a thread (block on its termination).
659///
e9174d1e 660/// A `JoinHandle` *detaches* the child thread when it is dropped.
85aaf69f
SL
661///
662/// Due to platform restrictions, it is not possible to `Clone` this
663/// handle: the ability to join a child thread is a uniquely-owned
664/// permission.
3157f602
XL
665///
666/// This `struct` is created by the [`thread::spawn`] function and the
667/// [`thread::Builder::spawn`] method.
668///
669/// # Examples
670///
671/// Creation from [`thread::spawn`]:
672///
673/// ```rust
674/// use std::thread;
675///
676/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| {
677/// // some work here
678/// });
679/// ```
680///
681/// Creation from [`thread::Builder::spawn`]:
682///
683/// ```rust
684/// use std::thread;
685///
686/// let builder = thread::Builder::new();
687///
688/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
689/// // some work here
690/// }).unwrap();
691/// ```
692///
693/// [`thread::spawn`]: fn.spawn.html
694/// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn
85aaf69f 695#[stable(feature = "rust1", since = "1.0.0")]
9346a6ac 696pub struct JoinHandle<T>(JoinInner<T>);
85aaf69f 697
9346a6ac
AL
698impl<T> JoinHandle<T> {
699 /// Extracts a handle to the underlying thread
85aaf69f
SL
700 #[stable(feature = "rust1", since = "1.0.0")]
701 pub fn thread(&self) -> &Thread {
702 &self.0.thread
703 }
704
9346a6ac 705 /// Waits for the associated thread to finish.
85aaf69f
SL
706 ///
707 /// If the child thread panics, `Err` is returned with the parameter given
708 /// to `panic`.
709 #[stable(feature = "rust1", since = "1.0.0")]
9346a6ac 710 pub fn join(mut self) -> Result<T> {
85aaf69f
SL
711 self.0.join()
712 }
713}
714
92a42be0
SL
715impl<T> AsInner<imp::Thread> for JoinHandle<T> {
716 fn as_inner(&self) -> &imp::Thread { self.0.native.as_ref().unwrap() }
717}
718
719impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
720 fn into_inner(self) -> imp::Thread { self.0.native.unwrap() }
721}
722
d9579d0f
AL
723fn _assert_sync_and_send() {
724 fn _assert_both<T: Send + Sync>() {}
725 _assert_both::<JoinHandle<()>>();
d9579d0f
AL
726 _assert_both::<Thread>();
727}
728
c34b1796
AL
729////////////////////////////////////////////////////////////////////////////////
730// Tests
731////////////////////////////////////////////////////////////////////////////////
732
1a4d82fc 733#[cfg(test)]
d9579d0f 734mod tests {
1a4d82fc
JJ
735 use prelude::v1::*;
736
737 use any::Any;
738 use sync::mpsc::{channel, Sender};
1a4d82fc 739 use result;
c34b1796 740 use super::{Builder};
85aaf69f 741 use thread;
85aaf69f 742 use time::Duration;
c34b1796 743 use u32;
1a4d82fc
JJ
744
745 // !!! These tests are dangerous. If something is buggy, they will hang, !!!
746 // !!! instead of exiting cleanly. This might wedge the buildbots. !!!
747
748 #[test]
749 fn test_unnamed_thread() {
85aaf69f
SL
750 thread::spawn(move|| {
751 assert!(thread::current().name().is_none());
752 }).join().ok().unwrap();
1a4d82fc
JJ
753 }
754
755 #[test]
756 fn test_named_thread() {
e9174d1e 757 Builder::new().name("ada lovelace".to_string()).spawn(move|| {
85aaf69f 758 assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
e9174d1e 759 }).unwrap().join().unwrap();
1a4d82fc
JJ
760 }
761
54a0048b
SL
762 #[test]
763 #[should_panic]
764 fn test_invalid_named_thread() {
765 let _ = Builder::new().name("ada l\0velace".to_string()).spawn(|| {});
766 }
767
1a4d82fc
JJ
768 #[test]
769 fn test_run_basic() {
770 let (tx, rx) = channel();
85aaf69f 771 thread::spawn(move|| {
1a4d82fc
JJ
772 tx.send(()).unwrap();
773 });
774 rx.recv().unwrap();
775 }
776
1a4d82fc
JJ
777 #[test]
778 fn test_join_panic() {
85aaf69f 779 match thread::spawn(move|| {
1a4d82fc
JJ
780 panic!()
781 }).join() {
782 result::Result::Err(_) => (),
783 result::Result::Ok(()) => panic!()
784 }
785 }
786
787 #[test]
788 fn test_spawn_sched() {
789 use clone::Clone;
790
791 let (tx, rx) = channel();
792
c34b1796 793 fn f(i: i32, tx: Sender<()>) {
1a4d82fc 794 let tx = tx.clone();
85aaf69f 795 thread::spawn(move|| {
1a4d82fc
JJ
796 if i == 0 {
797 tx.send(()).unwrap();
798 } else {
799 f(i - 1, tx);
800 }
801 });
802
803 }
804 f(10, tx);
805 rx.recv().unwrap();
806 }
807
808 #[test]
809 fn test_spawn_sched_childs_on_default_sched() {
810 let (tx, rx) = channel();
811
85aaf69f
SL
812 thread::spawn(move|| {
813 thread::spawn(move|| {
1a4d82fc
JJ
814 tx.send(()).unwrap();
815 });
816 });
817
818 rx.recv().unwrap();
819 }
820
e9174d1e 821 fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<Fn() + Send>) {
c34b1796 822 let (tx, rx) = channel();
1a4d82fc 823
c34b1796
AL
824 let x: Box<_> = box 1;
825 let x_in_parent = (&*x) as *const i32 as usize;
1a4d82fc 826
c34b1796
AL
827 spawnfn(Box::new(move|| {
828 let x_in_child = (&*x) as *const i32 as usize;
1a4d82fc
JJ
829 tx.send(x_in_child).unwrap();
830 }));
831
832 let x_in_child = rx.recv().unwrap();
833 assert_eq!(x_in_parent, x_in_child);
834 }
835
836 #[test]
837 fn test_avoid_copying_the_body_spawn() {
838 avoid_copying_the_body(|v| {
c34b1796 839 thread::spawn(move || v());
1a4d82fc
JJ
840 });
841 }
842
843 #[test]
844 fn test_avoid_copying_the_body_thread_spawn() {
845 avoid_copying_the_body(|f| {
85aaf69f 846 thread::spawn(move|| {
c34b1796 847 f();
1a4d82fc
JJ
848 });
849 })
850 }
851
852 #[test]
853 fn test_avoid_copying_the_body_join() {
854 avoid_copying_the_body(|f| {
85aaf69f 855 let _ = thread::spawn(move|| {
c34b1796 856 f()
1a4d82fc
JJ
857 }).join();
858 })
859 }
860
861 #[test]
862 fn test_child_doesnt_ref_parent() {
bd371182
AL
863 // If the child refcounts the parent thread, this will stack overflow when
864 // climbing the thread tree to dereference each ancestor. (See #1789)
1a4d82fc
JJ
865 // (well, it would if the constant were 8000+ - I lowered it to be more
866 // valgrind-friendly. try this at home, instead..!)
c34b1796 867 const GENERATIONS: u32 = 16;
e9174d1e 868 fn child_no(x: u32) -> Box<Fn() + Send> {
c34b1796 869 return Box::new(move|| {
1a4d82fc 870 if x < GENERATIONS {
c34b1796 871 thread::spawn(move|| child_no(x+1)());
1a4d82fc
JJ
872 }
873 });
874 }
c34b1796 875 thread::spawn(|| child_no(0)());
1a4d82fc
JJ
876 }
877
878 #[test]
879 fn test_simple_newsched_spawn() {
85aaf69f 880 thread::spawn(move || {});
1a4d82fc
JJ
881 }
882
883 #[test]
884 fn test_try_panic_message_static_str() {
85aaf69f 885 match thread::spawn(move|| {
1a4d82fc
JJ
886 panic!("static string");
887 }).join() {
888 Err(e) => {
889 type T = &'static str;
890 assert!(e.is::<T>());
c34b1796 891 assert_eq!(*e.downcast::<T>().unwrap(), "static string");
1a4d82fc
JJ
892 }
893 Ok(()) => panic!()
894 }
895 }
896
897 #[test]
898 fn test_try_panic_message_owned_str() {
85aaf69f 899 match thread::spawn(move|| {
1a4d82fc
JJ
900 panic!("owned string".to_string());
901 }).join() {
902 Err(e) => {
903 type T = String;
904 assert!(e.is::<T>());
c34b1796 905 assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
1a4d82fc
JJ
906 }
907 Ok(()) => panic!()
908 }
909 }
910
911 #[test]
912 fn test_try_panic_message_any() {
85aaf69f 913 match thread::spawn(move|| {
1a4d82fc
JJ
914 panic!(box 413u16 as Box<Any + Send>);
915 }).join() {
916 Err(e) => {
917 type T = Box<Any + Send>;
918 assert!(e.is::<T>());
c34b1796 919 let any = e.downcast::<T>().unwrap();
1a4d82fc 920 assert!(any.is::<u16>());
c34b1796 921 assert_eq!(*any.downcast::<u16>().unwrap(), 413);
1a4d82fc
JJ
922 }
923 Ok(()) => panic!()
924 }
925 }
926
927 #[test]
928 fn test_try_panic_message_unit_struct() {
929 struct Juju;
930
85aaf69f 931 match thread::spawn(move|| {
1a4d82fc
JJ
932 panic!(Juju)
933 }).join() {
934 Err(ref e) if e.is::<Juju>() => {}
935 Err(_) | Ok(()) => panic!()
936 }
937 }
938
85aaf69f
SL
939 #[test]
940 fn test_park_timeout_unpark_before() {
941 for _ in 0..10 {
942 thread::current().unpark();
9cc50fc6 943 thread::park_timeout(Duration::from_millis(u32::MAX as u64));
85aaf69f
SL
944 }
945 }
946
947 #[test]
948 fn test_park_timeout_unpark_not_called() {
949 for _ in 0..10 {
9cc50fc6 950 thread::park_timeout(Duration::from_millis(10));
85aaf69f
SL
951 }
952 }
953
954 #[test]
955 fn test_park_timeout_unpark_called_other_thread() {
85aaf69f
SL
956 for _ in 0..10 {
957 let th = thread::current();
958
959 let _guard = thread::spawn(move || {
9cc50fc6 960 super::sleep(Duration::from_millis(50));
85aaf69f
SL
961 th.unpark();
962 });
963
9cc50fc6 964 thread::park_timeout(Duration::from_millis(u32::MAX as u64));
85aaf69f
SL
965 }
966 }
967
c34b1796
AL
968 #[test]
969 fn sleep_ms_smoke() {
9cc50fc6 970 thread::sleep(Duration::from_millis(2));
c34b1796
AL
971 }
972
bd371182 973 // NOTE: the corresponding test for stderr is in run-pass/thread-stderr, due
1a4d82fc
JJ
974 // to the test harness apparently interfering with stderr configuration.
975}