]>
Commit | Line | Data |
---|---|---|
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 | ||
164 | use prelude::v1::*; | |
1a4d82fc JJ |
165 | |
166 | use any::Any; | |
1a4d82fc | 167 | use cell::UnsafeCell; |
a7813a04 | 168 | use ffi::{CStr, CString}; |
85aaf69f SL |
169 | use fmt; |
170 | use io; | |
a7813a04 XL |
171 | use panic; |
172 | use panicking; | |
54a0048b | 173 | use str; |
85aaf69f | 174 | use sync::{Mutex, Condvar, Arc}; |
c34b1796 | 175 | use sys::thread as imp; |
e9174d1e | 176 | use sys_common::thread_info; |
e9174d1e | 177 | use sys_common::util; |
92a42be0 | 178 | use sys_common::{AsInner, IntoInner}; |
85aaf69f | 179 | use 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")] | |
188 | pub 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 |
203 | pub 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 | ||
210 | impl 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 |
318 | pub 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")] | |
326 | pub 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")] |
334 | pub 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")] | |
370 | pub 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 | 382 | pub 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 |
411 | pub 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")] | |
441 | pub 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 | 467 | pub 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 | 506 | pub 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 | 521 | struct 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. |
530 | pub struct Thread { | |
531 | inner: Arc<Inner>, | |
532 | } | |
533 | ||
534 | impl 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")] | |
604 | impl 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 | |
611 | impl 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")] |
623 | pub 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 |
637 | struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>); |
638 | ||
d9579d0f AL |
639 | unsafe impl<T: Send> Send for Packet<T> {} |
640 | unsafe impl<T: Sync> Sync for Packet<T> {} | |
1a4d82fc | 641 | |
e9174d1e | 642 | /// Inner representation for JoinHandle |
85aaf69f | 643 | struct JoinInner<T> { |
d9579d0f | 644 | native: Option<imp::Thread>, |
85aaf69f SL |
645 | thread: Thread, |
646 | packet: Packet<T>, | |
85aaf69f SL |
647 | } |
648 | ||
649 | impl<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 | 696 | pub struct JoinHandle<T>(JoinInner<T>); |
85aaf69f | 697 | |
9346a6ac AL |
698 | impl<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 |
715 | impl<T> AsInner<imp::Thread> for JoinHandle<T> { |
716 | fn as_inner(&self) -> &imp::Thread { self.0.native.as_ref().unwrap() } | |
717 | } | |
718 | ||
719 | impl<T> IntoInner<imp::Thread> for JoinHandle<T> { | |
720 | fn into_inner(self) -> imp::Thread { self.0.native.unwrap() } | |
721 | } | |
722 | ||
d9579d0f AL |
723 | fn _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 | 734 | mod 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 | } |