16
16
//! each with their own stack and local state.
17
17
//!
18
18
//! Communication between threads can be done through
19
- //! [channels](../../std/comm /index.html), Rust's message-passing
19
+ //! [channels](../../std/sync/mpsc /index.html), Rust's message-passing
20
20
//! types, along with [other forms of thread
21
21
//! synchronization](../../std/sync/index.html) and shared-memory data
22
22
//! structures. In particular, types that are guaranteed to be
58
58
//! ```rust
59
59
//! use std::thread::Thread;
60
60
//!
61
- //! let guard = Thread::spawn(move || {
61
+ //! let thread = Thread::spawn(move || {
62
62
//! println!("Hello, World!");
63
63
//! // some computation here
64
64
//! });
65
- //! let result = guard.join();
66
65
//! ```
67
66
//!
68
- //! The `spawn` function doesn't return a `Thread` directly; instead, it returns
69
- //! a *join guard* from which a `Thread` can be extracted. The join guard is an
70
- //! RAII-style guard that will automatically join the child thread (block until
71
- //! it terminates) when it is dropped. You can join the child thread in advance
72
- //! by calling the `join` method on the guard, which will also return the result
73
- //! produced by the thread.
67
+ //! The spawned thread is "detached" from the current thread, meaning that it
68
+ //! can outlive the thread that spawned it. (Note, however, that when the main
69
+ //! thread terminates all detached threads are terminated as well.) The returned
70
+ //! `Thread` handle can be used for low-level synchronization as described below.
71
+ //!
72
+ //! ## Scoped threads
73
+ //!
74
+ //! Often a parent thread uses a child thread to perform some particular task,
75
+ //! and at some point must wait for the child to complete before continuing.
76
+ //! For this scenario, use the `scoped` constructor:
77
+ //!
78
+ //! ```rust
79
+ //! use std::thread::Thread;
80
+ //!
81
+ //! let guard = Thread::scoped(move || {
82
+ //! println!("Hello, World!");
83
+ //! // some computation here
84
+ //! });
85
+ //! // do some other work in the meantime
86
+ //! let result = guard.join();
87
+ //! ```
74
88
//!
75
- //! If you instead wish to *detach* the child thread, allowing it to outlive its
76
- //! parent, you can use the `detach` method on the guard,
89
+ //! The `scoped` function doesn't return a `Thread` directly; instead, it
90
+ //! returns a *join guard* from which a `Thread` can be extracted. The join
91
+ //! guard is an RAII-style guard that will automatically join the child thread
92
+ //! (block until it terminates) when it is dropped. You can join the child
93
+ //! thread in advance by calling the `join` method on the guard, which will also
94
+ //! return the result produced by the thread. A handle to the thread itself is
95
+ //! available via the `thread` method on the join guard.
77
96
//!
78
- //! A handle to the thread itself is available via the `thread` method on the
79
- //! join guard.
97
+ //! (Note: eventually, the `scoped` constructor will allow the parent and child
98
+ //! threads to data that lives on the parent thread's stack, but some language
99
+ //! changes are needed before this is possible.)
80
100
//!
81
101
//! ## Configuring threads
82
102
//!
89
109
//!
90
110
//! thread::Builder::new().name("child1".to_string()).spawn(move || {
91
111
//! println!("Hello, world!")
92
- //! }).detach() ;
112
+ //! });
93
113
//! ```
94
114
//!
95
115
//! ## Blocking support: park and unpark
124
144
//!
125
145
//! * It can be implemented highly efficiently on many platforms.
126
146
147
+ #![ stable]
148
+
127
149
use any:: Any ;
128
150
use boxed:: Box ;
129
151
use cell:: UnsafeCell ;
@@ -144,6 +166,7 @@ use sys_common::{stack, thread_info};
144
166
145
167
/// Thread configuation. Provides detailed control over the properties
146
168
/// and behavior of new threads.
169
+ #[ stable]
147
170
pub struct Builder {
148
171
// A name for the thread-to-be, for identification in panic messages
149
172
name : Option < String > ,
@@ -158,6 +181,7 @@ pub struct Builder {
158
181
impl Builder {
159
182
/// Generate the base configuration for spawning a thread, from which
160
183
/// configuration methods can be chained.
184
+ #[ stable]
161
185
pub fn new ( ) -> Builder {
162
186
Builder {
163
187
name : None ,
@@ -169,12 +193,14 @@ impl Builder {
169
193
170
194
/// Name the thread-to-be. Currently the name is used for identification
171
195
/// only in panic messages.
196
+ #[ stable]
172
197
pub fn name ( mut self , name : String ) -> Builder {
173
198
self . name = Some ( name) ;
174
199
self
175
200
}
176
201
177
202
/// Set the size of the stack for the new thread.
203
+ #[ stable]
178
204
pub fn stack_size ( mut self , size : uint ) -> Builder {
179
205
self . stack_size = Some ( size) ;
180
206
self
@@ -194,19 +220,41 @@ impl Builder {
194
220
self
195
221
}
196
222
197
- /// Spawn a new joinable thread, and return a JoinGuard guard for it.
223
+ /// Spawn a new detached thread, and return a handle to it.
198
224
///
199
225
/// See `Thead::spawn` and the module doc for more details.
200
- pub fn spawn < T , F > ( self , f : F ) -> JoinGuard < T > where
201
- T : Send , F : FnOnce ( ) -> T , F : Send
202
- {
203
- self . spawn_inner ( Thunk :: new ( f) )
226
+ #[ unstable = "may change with specifics of new Send semantics" ]
227
+ pub fn spawn < F > ( self , f : F ) -> Thread where F : FnOnce ( ) , F : Send + ' static {
228
+ let ( native, thread) = self . spawn_inner ( Thunk :: new ( f) , Thunk :: with_arg ( |_| { } ) ) ;
229
+ unsafe { imp:: detach ( native) } ;
230
+ thread
204
231
}
205
232
206
- fn spawn_inner < T : Send > ( self , f : Thunk < ( ) , T > ) -> JoinGuard < T > {
233
+ /// Spawn a new child thread that must be joined within a given
234
+ /// scope, and return a `JoinGuard`.
235
+ ///
236
+ /// See `Thead::scoped` and the module doc for more details.
237
+ #[ unstable = "may change with specifics of new Send semantics" ]
238
+ pub fn scoped < ' a , T , F > ( self , f : F ) -> JoinGuard < ' a , T > where
239
+ T : Send + ' a , F : FnOnce ( ) -> T , F : Send + ' a
240
+ {
207
241
let my_packet = Packet ( Arc :: new ( UnsafeCell :: new ( None ) ) ) ;
208
242
let their_packet = Packet ( my_packet. 0 . clone ( ) ) ;
243
+ let ( native, thread) = self . spawn_inner ( Thunk :: new ( f) , Thunk :: with_arg ( move |: ret| unsafe {
244
+ * their_packet. 0 . get ( ) = Some ( ret) ;
245
+ } ) ) ;
209
246
247
+ JoinGuard {
248
+ native : native,
249
+ joined : false ,
250
+ packet : my_packet,
251
+ thread : thread,
252
+ }
253
+ }
254
+
255
+ fn spawn_inner < T : Send > ( self , f : Thunk < ( ) , T > , finish : Thunk < Result < T > , ( ) > )
256
+ -> ( imp:: rust_thread , Thread )
257
+ {
210
258
let Builder { name, stack_size, stdout, stderr } = self ;
211
259
212
260
let stack_size = stack_size. unwrap_or ( rt:: min_stack ( ) ) ;
@@ -258,21 +306,14 @@ impl Builder {
258
306
unwind:: try ( move || * ptr = Some ( f. invoke ( ( ) ) ) )
259
307
}
260
308
} ;
261
- unsafe {
262
- * their_packet. 0 . get ( ) = Some ( match ( output, try_result) {
263
- ( Some ( data) , Ok ( _) ) => Ok ( data) ,
264
- ( None , Err ( cause) ) => Err ( cause) ,
265
- _ => unreachable ! ( )
266
- } ) ;
267
- }
309
+ finish. invoke ( match ( output, try_result) {
310
+ ( Some ( data) , Ok ( _) ) => Ok ( data) ,
311
+ ( None , Err ( cause) ) => Err ( cause) ,
312
+ _ => unreachable ! ( )
313
+ } ) ;
268
314
} ;
269
315
270
- JoinGuard {
271
- native : unsafe { imp:: create ( stack_size, Thunk :: new ( main) ) } ,
272
- joined : false ,
273
- packet : my_packet,
274
- thread : my_thread,
275
- }
316
+ ( unsafe { imp:: create ( stack_size, Thunk :: new ( main) ) } , my_thread)
276
317
}
277
318
}
278
319
@@ -285,11 +326,13 @@ struct Inner {
285
326
unsafe impl Sync for Inner { }
286
327
287
328
#[ derive( Clone ) ]
329
+ #[ stable]
288
330
/// A handle to a thread.
289
331
pub struct Thread {
290
332
inner : Arc < Inner > ,
291
333
}
292
334
335
+ #[ stable]
293
336
unsafe impl Sync for Thread { }
294
337
295
338
impl Thread {
@@ -304,30 +347,47 @@ impl Thread {
304
347
}
305
348
}
306
349
307
- /// Spawn a new joinable thread, returning a `JoinGuard` for it.
350
+ /// Spawn a new detached thread, returning a handle to it.
351
+ ///
352
+ /// The child thread may outlive the parent (unless the parent thread is the
353
+ /// main thread; the whole process is terminated when the main thread
354
+ /// finishes.) The thread handle can be used for low-level
355
+ /// synchronization. See the module documentation for additional details.
356
+ #[ unstable = "may change with specifics of new Send semantics" ]
357
+ pub fn spawn < F > ( f : F ) -> Thread where F : FnOnce ( ) , F : Send + ' static {
358
+ Builder :: new ( ) . spawn ( f)
359
+ }
360
+
361
+ /// Spawn a new *scoped* thread, returning a `JoinGuard` for it.
308
362
///
309
363
/// The join guard can be used to explicitly join the child thread (via
310
364
/// `join`), returning `Result<T>`, or it will implicitly join the child
311
- /// upon being dropped. To detach the child, allowing it to outlive the
312
- /// current thread, use `detach`. See the module documentation for additional details.
313
- pub fn spawn < T , F > ( f : F ) -> JoinGuard < T > where
314
- T : Send , F : FnOnce ( ) -> T , F : Send
365
+ /// upon being dropped. Because the child thread may refer to data on the
366
+ /// current thread's stack (hence the "scoped" name), it cannot be detached;
367
+ /// it *must* be joined before the relevant stack frame is popped. See the
368
+ /// module documentation for additional details.
369
+ #[ unstable = "may change with specifics of new Send semantics" ]
370
+ pub fn scoped < ' a , T , F > ( f : F ) -> JoinGuard < ' a , T > where
371
+ T : Send + ' a , F : FnOnce ( ) -> T , F : Send + ' a
315
372
{
316
- Builder :: new ( ) . spawn ( f)
373
+ Builder :: new ( ) . scoped ( f)
317
374
}
318
375
319
376
/// Gets a handle to the thread that invokes it.
377
+ #[ stable]
320
378
pub fn current ( ) -> Thread {
321
379
thread_info:: current_thread ( )
322
380
}
323
381
324
382
/// Cooperatively give up a timeslice to the OS scheduler.
383
+ #[ unstable = "name may change" ]
325
384
pub fn yield_now ( ) {
326
385
unsafe { imp:: yield_now ( ) }
327
386
}
328
387
329
388
/// Determines whether the current thread is panicking.
330
389
#[ inline]
390
+ #[ stable]
331
391
pub fn panicking ( ) -> bool {
332
392
unwind:: panicking ( )
333
393
}
@@ -341,6 +401,7 @@ impl Thread {
341
401
// future, this will be implemented in a more efficient way, perhaps along the lines of
342
402
// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
343
403
// or futuxes, and in either case may allow spurious wakeups.
404
+ #[ unstable = "recently introduced" ]
344
405
pub fn park ( ) {
345
406
let thread = Thread :: current ( ) ;
346
407
let mut guard = thread. inner . lock . lock ( ) . unwrap ( ) ;
@@ -353,6 +414,7 @@ impl Thread {
353
414
/// Atomically makes the handle's token available if it is not already.
354
415
///
355
416
/// See the module doc for more detail.
417
+ #[ unstable = "recently introduced" ]
356
418
pub fn unpark ( & self ) {
357
419
let mut guard = self . inner . lock . lock ( ) . unwrap ( ) ;
358
420
if !* guard {
@@ -362,6 +424,7 @@ impl Thread {
362
424
}
363
425
364
426
/// Get the thread's name.
427
+ #[ stable]
365
428
pub fn name ( & self ) -> Option < & str > {
366
429
self . inner . name . as_ref ( ) . map ( |s| s. as_slice ( ) )
367
430
}
@@ -375,28 +438,32 @@ impl thread_info::NewThread for Thread {
375
438
/// Indicates the manner in which a thread exited.
376
439
///
377
440
/// A thread that completes without panicking is considered to exit successfully.
441
+ #[ stable]
378
442
pub type Result < T > = :: result:: Result < T , Box < Any + Send > > ;
379
443
380
444
struct Packet < T > ( Arc < UnsafeCell < Option < Result < T > > > > ) ;
381
445
382
446
unsafe impl < T : ' static +Send > Send for Packet < T > { }
383
447
unsafe impl < T > Sync for Packet < T > { }
384
448
385
- #[ must_use]
386
449
/// An RAII-style guard that will block until thread termination when dropped.
387
450
///
388
451
/// The type `T` is the return type for the thread's main function.
389
- pub struct JoinGuard < T > {
452
+ #[ must_use]
453
+ #[ unstable = "may change with specifics of new Send semantics" ]
454
+ pub struct JoinGuard < ' a , T : ' a > {
390
455
native : imp:: rust_thread ,
391
456
thread : Thread ,
392
457
joined : bool ,
393
458
packet : Packet < T > ,
394
459
}
395
460
396
- unsafe impl < T : Send > Sync for JoinGuard < T > { }
461
+ #[ stable]
462
+ unsafe impl < ' a , T : Send + ' a > Sync for JoinGuard < ' a , T > { }
397
463
398
- impl < T : Send > JoinGuard < T > {
464
+ impl < ' a , T : Send + ' a > JoinGuard < ' a , T > {
399
465
/// Extract a handle to the thread this guard will join on.
466
+ #[ stable]
400
467
pub fn thread ( & self ) -> & Thread {
401
468
& self . thread
402
469
}
@@ -406,6 +473,7 @@ impl<T: Send> JoinGuard<T> {
406
473
///
407
474
/// If the child thread panics, `Err` is returned with the parameter given
408
475
/// to `panic`.
476
+ #[ stable]
409
477
pub fn join ( mut self ) -> Result < T > {
410
478
assert ! ( !self . joined) ;
411
479
unsafe { imp:: join ( self . native ) } ;
@@ -414,8 +482,11 @@ impl<T: Send> JoinGuard<T> {
414
482
( * self . packet . 0 . get ( ) ) . take ( ) . unwrap ( )
415
483
}
416
484
}
485
+ }
417
486
487
+ impl < T : Send > JoinGuard < ' static , T > {
418
488
/// Detaches the child thread, allowing it to outlive its parent.
489
+ #[ experimental = "unsure whether this API imposes limitations elsewhere" ]
419
490
pub fn detach ( mut self ) {
420
491
unsafe { imp:: detach ( self . native ) } ;
421
492
self . joined = true ; // avoid joining in the destructor
@@ -424,7 +495,7 @@ impl<T: Send> JoinGuard<T> {
424
495
425
496
#[ unsafe_destructor]
426
497
#[ stable]
427
- impl < T : Send > Drop for JoinGuard < T > {
498
+ impl < ' a , T : Send + ' a > Drop for JoinGuard < ' a , T > {
428
499
fn drop ( & mut self ) {
429
500
if !self . joined {
430
501
unsafe { imp:: join ( self . native ) } ;
0 commit comments