13
13
*
14
14
* An executing Rust program consists of a tree of tasks, each with their own
15
15
* stack, and sole ownership of their allocated heap data. Tasks communicate
16
- * with each other using ports and channels (see std::rt:: comm for more info
16
+ * with each other using ports and channels (see std::comm for more info
17
17
* about how communication works).
18
18
*
19
- * Tasks can be spawned in 3 different modes.
20
- *
21
- * * Bidirectionally linked: This is the default mode and it's what ```spawn``` does.
22
- * Failures will be propagated from parent to child and vice versa.
23
- *
24
- * * Unidirectionally linked (parent->child): This type of task can be created with
25
- * ```spawn_supervised```. In this case, failures are propagated from parent to child
26
- * but not the other way around.
27
- *
28
- * * Unlinked: Tasks can be completely unlinked. These tasks can be created by using
29
- * ```spawn_unlinked```. In this case failures are not propagated at all.
30
- *
31
- * Tasks' failure modes can be further configured. For instance, parent tasks can (un)watch
32
- * children failures. Please, refer to TaskBuilder's documentation bellow for more information.
33
- *
34
- * When a (bi|uni)directionally linked task fails, its failure will be propagated to all tasks
35
- * linked to it, this will cause such tasks to fail by a `linked failure`.
19
+ * Failure in one task does not propagate to any others (not to parent, not to child).
20
+ * Failure propagation is instead handled by using Chan.send() and Port.recv(), which
21
+ * will fail if the other end has hung up already.
36
22
*
37
23
* Task Scheduling:
38
24
*
51
37
* ```
52
38
*/
53
39
54
- #[ allow( missing_doc) ] ;
55
-
56
40
use any:: Any ;
57
41
use comm:: { Chan , Port } ;
58
42
use io:: Writer ;
@@ -70,40 +54,24 @@ use str::{Str, SendStr, IntoMaybeOwned};
70
54
/// Indicates the manner in which a task exited.
71
55
///
72
56
/// A task that completes without failing is considered to exit successfully.
73
- /// Supervised ancestors and linked siblings may yet fail after this task
74
- /// succeeds. Also note that in such a case, it may be nondeterministic whether
75
- /// linked failure or successful exit happen first.
76
57
///
77
- /// If you wish for this result's delivery to block until all linked and/or
58
+ /// If you wish for this result's delivery to block until all
78
59
/// children tasks complete, recommend using a result future.
79
60
pub type TaskResult = Result < ( ) , ~Any > ;
80
61
81
- /**
82
- * Task configuration options
83
- *
84
- * # Fields
85
- *
86
- * * watched - Make parent task collect exit status notifications from child
87
- * before reporting its own exit status. (This delays the parent
88
- * task's death and cleanup until after all transitively watched
89
- * children also exit.) True by default.
90
- *
91
- * * notify_chan - Enable lifecycle notifications on the given channel
92
- *
93
- * * name - A name for the task-to-be, for identification in failure messages.
94
- *
95
- * * sched - Specify the configuration of a new scheduler to create the task
96
- * in. This is of particular importance for libraries which want to call
97
- * into foreign code that blocks. Without doing so in a different
98
- * scheduler other tasks will be impeded or even blocked indefinitely.
99
- */
62
+ /// Task configuration options
100
63
pub struct TaskOpts {
101
- watched : bool ,
64
+ /// Enable lifecycle notifications on the given channel
102
65
notify_chan : Option < Chan < TaskResult > > ,
66
+ /// A name for the task-to-be, for identification in failure messages
103
67
name : Option < SendStr > ,
68
+ /// The size of the stack for the spawned task
104
69
stack_size : Option < uint > ,
70
+ /// Task-local logger (see std::logging)
105
71
logger : Option < ~Logger > ,
72
+ /// Task-local stdout
106
73
stdout : Option < ~Writer > ,
74
+ /// Task-local stderr
107
75
stderr : Option < ~Writer > ,
108
76
}
109
77
@@ -120,6 +88,7 @@ pub struct TaskOpts {
120
88
// sidestep that whole issue by making builders uncopyable and making
121
89
// the run function move them in.
122
90
pub struct TaskBuilder {
91
+ /// Options to spawn the new task with
123
92
opts : TaskOpts ,
124
93
priv gen_body : Option < proc ( v : proc ( ) ) -> proc ( ) > ,
125
94
priv nopod : Option < marker:: NoPod > ,
@@ -128,7 +97,6 @@ pub struct TaskBuilder {
128
97
/**
129
98
* Generate the base configuration for spawning a task, off of which more
130
99
* configuration methods can be chained.
131
- * For example, task().unlinked().spawn is equivalent to spawn_unlinked.
132
100
*/
133
101
pub fn task ( ) -> TaskBuilder {
134
102
TaskBuilder {
@@ -139,31 +107,13 @@ pub fn task() -> TaskBuilder {
139
107
}
140
108
141
109
impl TaskBuilder {
142
- /// Cause the parent task to collect the child's exit status (and that of
143
- /// all transitively-watched grandchildren) before reporting its own.
144
- pub fn watched ( & mut self ) {
145
- self . opts . watched = true ;
146
- }
147
-
148
- /// Allow the child task to outlive the parent task, at the possible cost
149
- /// of the parent reporting success even if the child task fails later.
150
- pub fn unwatched ( & mut self ) {
151
- self . opts . watched = false ;
152
- }
153
-
154
110
/// Get a future representing the exit status of the task.
155
111
///
156
112
/// Taking the value of the future will block until the child task
157
113
/// terminates. The future result return value will be created *before* the task is
158
114
/// spawned; as such, do not invoke .get() on it directly;
159
115
/// rather, store it in an outer variable/list for later use.
160
116
///
161
- /// Note that the future returned by this function is only useful for
162
- /// obtaining the value of the next task to be spawning with the
163
- /// builder. If additional tasks are spawned with the same builder
164
- /// then a new result future must be obtained prior to spawning each
165
- /// task.
166
- ///
167
117
/// # Failure
168
118
/// Fails if a future_result was already set for this task.
169
119
pub fn future_result ( & mut self ) -> Port < TaskResult > {
@@ -187,8 +137,9 @@ impl TaskBuilder {
187
137
188
138
/// Name the task-to-be. Currently the name is used for identification
189
139
/// only in failure messages.
190
- pub fn name < S : IntoMaybeOwned < ' static > > ( & mut self , name : S ) {
140
+ pub fn named < S : IntoMaybeOwned < ' static > > ( mut self , name : S ) -> TaskBuilder {
191
141
self . opts . name = Some ( name. into_maybe_owned ( ) ) ;
142
+ self
192
143
}
193
144
194
145
/**
@@ -203,7 +154,7 @@ impl TaskBuilder {
203
154
* generator by applying the task body which results from the
204
155
* existing body generator to the new body generator.
205
156
*/
206
- pub fn add_wrapper ( & mut self , wrapper : proc ( v : proc ( ) ) -> proc ( ) ) {
157
+ pub fn with_wrapper ( mut self , wrapper : proc ( v : proc ( ) ) -> proc ( ) ) -> TaskBuilder {
207
158
let prev_gen_body = self . gen_body . take ( ) ;
208
159
let prev_gen_body = match prev_gen_body {
209
160
Some ( gen) => gen,
@@ -219,6 +170,7 @@ impl TaskBuilder {
219
170
f
220
171
} ;
221
172
self . gen_body = Some ( next_gen_body) ;
173
+ self
222
174
}
223
175
224
176
/**
@@ -227,11 +179,6 @@ impl TaskBuilder {
227
179
* Sets up a new task with its own call stack and schedules it to run
228
180
* the provided unique closure. The task has the properties and behavior
229
181
* specified by the task_builder.
230
- *
231
- * # Failure
232
- *
233
- * When spawning into a new scheduler, the number of threads requested
234
- * must be greater than zero.
235
182
*/
236
183
pub fn spawn ( mut self , f : proc ( ) ) {
237
184
let gen_body = self . gen_body . take ( ) ;
@@ -278,13 +225,9 @@ impl TaskOpts {
278
225
pub fn new ( ) -> TaskOpts {
279
226
/*!
280
227
* The default task options
281
- *
282
- * By default all tasks are supervised by their parent, are spawned
283
- * into the same scheduler, and do not post lifecycle notifications.
284
228
*/
285
229
286
230
TaskOpts {
287
- watched : true ,
288
231
notify_chan : None ,
289
232
name : None ,
290
233
stack_size : None ,
@@ -313,7 +256,7 @@ pub fn try<T:Send>(f: proc() -> T) -> Result<T, ~Any> {
313
256
* Execute a function in another task and return either the return value
314
257
* of the function or result::err.
315
258
*
316
- * This is equivalent to task().supervised(). try.
259
+ * This is equivalent to task().try.
317
260
*/
318
261
319
262
let task = task ( ) ;
@@ -370,9 +313,7 @@ fn test_unnamed_task() {
370
313
371
314
#[ test]
372
315
fn test_owned_named_task ( ) {
373
- let mut t = task ( ) ;
374
- t. name ( ~"ada lovelace") ;
375
- t. spawn ( proc ( ) {
316
+ task ( ) . named ( ~"ada lovelace") . spawn ( proc ( ) {
376
317
with_task_name ( |name| {
377
318
assert ! ( name. unwrap( ) == "ada lovelace" ) ;
378
319
} )
@@ -381,9 +322,7 @@ fn test_owned_named_task() {
381
322
382
323
#[ test]
383
324
fn test_static_named_task ( ) {
384
- let mut t = task ( ) ;
385
- t. name ( "ada lovelace" ) ;
386
- t. spawn ( proc ( ) {
325
+ task ( ) . named ( "ada lovelace" ) . spawn ( proc ( ) {
387
326
with_task_name ( |name| {
388
327
assert ! ( name. unwrap( ) == "ada lovelace" ) ;
389
328
} )
@@ -392,9 +331,7 @@ fn test_static_named_task() {
392
331
393
332
#[ test]
394
333
fn test_send_named_task ( ) {
395
- let mut t = task ( ) ;
396
- t. name ( "ada lovelace" . into_maybe_owned ( ) ) ;
397
- t. spawn ( proc ( ) {
334
+ task ( ) . named ( "ada lovelace" . into_maybe_owned ( ) ) . spawn ( proc ( ) {
398
335
with_task_name ( |name| {
399
336
assert ! ( name. unwrap( ) == "ada lovelace" ) ;
400
337
} )
@@ -411,18 +348,16 @@ fn test_run_basic() {
411
348
}
412
349
413
350
#[ test]
414
- fn test_add_wrapper ( ) {
351
+ fn test_with_wrapper ( ) {
415
352
let ( po, ch) = Chan :: new ( ) ;
416
- let mut b0 = task ( ) ;
417
- b0. add_wrapper ( proc ( body) {
353
+ task ( ) . with_wrapper ( proc ( body) {
418
354
let ch = ch;
419
355
let result: proc ( ) = proc ( ) {
420
356
body ( ) ;
421
357
ch. send ( ( ) ) ;
422
358
} ;
423
359
result
424
- } ) ;
425
- b0. spawn ( proc ( ) { } ) ;
360
+ } ) . spawn ( proc ( ) { } ) ;
426
361
po. recv ( ) ;
427
362
}
428
363
@@ -553,15 +488,11 @@ fn test_child_doesnt_ref_parent() {
553
488
fn child_no(x: uint) -> proc() {
554
489
return proc() {
555
490
if x < generations {
556
- let mut t = task();
557
- t.unwatched();
558
- t.spawn(child_no(x+1));
491
+ task().spawn(child_no(x+1));
559
492
}
560
493
}
561
494
}
562
- let mut t = task();
563
- t.unwatched();
564
- t.spawn(child_no(0));
495
+ task().spawn(child_no(0));
565
496
}
566
497
567
498
#[test]
0 commit comments