@@ -148,6 +148,17 @@ pub struct SchedOpts {
148
148
* * supervised - Propagate failure unidirectionally from parent to child,
149
149
* but not from child to parent. False by default.
150
150
*
151
+ * * watched - Make parent task collect exit status notifications from child
152
+ * before reporting its own exit status. (This delays the parent
153
+ * task's death and cleanup until after all transitively watched
154
+ * children also exit.) True by default.
155
+ *
156
+ * * indestructible - Configures the task to ignore kill signals received from
157
+ * linked failure. This may cause process hangs during
158
+ * failure if not used carefully, but causes task blocking
159
+ * code paths (e.g. port recv() calls) to be faster by 2
160
+ * atomic operations. False by default.
161
+ *
151
162
* * notify_chan - Enable lifecycle notifications on the given channel
152
163
*
153
164
* * sched - Specify the configuration of a new scheduler to create the task
@@ -166,6 +177,8 @@ pub struct SchedOpts {
166
177
pub struct TaskOpts {
167
178
linked : bool ,
168
179
supervised : bool ,
180
+ watched : bool ,
181
+ indestructible : bool ,
169
182
notify_chan : Option < Chan < TaskResult > > ,
170
183
sched : SchedOpts
171
184
}
@@ -217,6 +230,8 @@ impl TaskBuilder {
217
230
opts : TaskOpts {
218
231
linked : self . opts . linked ,
219
232
supervised : self . opts . supervised ,
233
+ watched : self . opts . watched ,
234
+ indestructible : self . opts . indestructible ,
220
235
notify_chan : notify_chan,
221
236
sched : self . opts . sched
222
237
} ,
@@ -232,6 +247,7 @@ impl TaskBuilder {
232
247
/// the other will not be killed.
233
248
pub fn unlinked ( & mut self ) {
234
249
self . opts . linked = false ;
250
+ self . opts . watched = false ;
235
251
}
236
252
237
253
/// Unidirectionally link the child task's failure with the parent's. The
@@ -240,13 +256,34 @@ impl TaskBuilder {
240
256
pub fn supervised ( & mut self ) {
241
257
self . opts . supervised = true ;
242
258
self . opts . linked = false ;
259
+ self . opts . watched = false ;
243
260
}
244
261
245
262
/// Link the child task's and parent task's failures. If either fails, the
246
263
/// other will be killed.
247
264
pub fn linked ( & mut self ) {
248
265
self . opts . linked = true ;
249
266
self . opts . supervised = false ;
267
+ self . opts . watched = true ;
268
+ }
269
+
270
+ /// Cause the parent task to collect the child's exit status (and that of
271
+ /// all transitively-watched grandchildren) before reporting its own.
272
+ pub fn watched ( & mut self ) {
273
+ self . opts . watched = true ;
274
+ }
275
+
276
+ /// Allow the child task to outlive the parent task, at the possible cost
277
+ /// of the parent reporting success even if the child task fails later.
278
+ pub fn unwatched ( & mut self ) {
279
+ self . opts . watched = false ;
280
+ }
281
+
282
+ /// Cause the child task to ignore any kill signals received from linked
283
+ /// failure. This optimizes context switching, at the possible expense of
284
+ /// process hangs in the case of unexpected failure.
285
+ pub fn indestructible ( & mut self ) {
286
+ self . opts . indestructible = true ;
250
287
}
251
288
252
289
/**
@@ -341,6 +378,8 @@ impl TaskBuilder {
341
378
let opts = TaskOpts {
342
379
linked : x. opts . linked ,
343
380
supervised : x. opts . supervised ,
381
+ watched : x. opts . watched ,
382
+ indestructible : x. opts . indestructible ,
344
383
notify_chan : notify_chan,
345
384
sched : x. opts . sched
346
385
} ;
@@ -407,6 +446,8 @@ pub fn default_task_opts() -> TaskOpts {
407
446
TaskOpts {
408
447
linked : true ,
409
448
supervised : false ,
449
+ watched : true ,
450
+ indestructible : false ,
410
451
notify_chan : None ,
411
452
sched : SchedOpts {
412
453
mode : DefaultScheduler ,
@@ -448,6 +489,17 @@ pub fn spawn_supervised(f: ~fn()) {
448
489
task. spawn ( f)
449
490
}
450
491
492
+ /// Creates a child task that cannot be killed by linked failure. This causes
493
+ /// its context-switch path to be faster by 2 atomic swap operations.
494
+ /// (Note that this convenience wrapper still uses linked-failure, so the
495
+ /// child's children will still be killable by the parent. For the fastest
496
+ /// possible spawn mode, use task::task().unlinked().indestructible().spawn.)
497
+ pub fn spawn_indestructible ( f : ~fn ( ) ) {
498
+ let mut task = task ( ) ;
499
+ task. indestructible ( ) ;
500
+ task. spawn ( f)
501
+ }
502
+
451
503
pub fn spawn_with < A : Send > ( arg : A , f : ~fn ( v : A ) ) {
452
504
/*!
453
505
* Runs a task, while transfering ownership of one argument to the
@@ -1209,3 +1261,61 @@ fn test_simple_newsched_spawn() {
1209
1261
}
1210
1262
}
1211
1263
1264
+ #[ test] #[ ignore( cfg( windows) ) ]
1265
+ fn test_spawn_watched( ) {
1266
+ use rt:: test:: { run_in_newsched_task, spawntask_try} ;
1267
+ do run_in_newsched_task {
1268
+ let result = do spawntask_try {
1269
+ let mut t = task( ) ;
1270
+ t. unlinked( ) ;
1271
+ t. watched( ) ;
1272
+ do t. spawn {
1273
+ let mut t = task( ) ;
1274
+ t. unlinked( ) ;
1275
+ t. watched( ) ;
1276
+ do t. spawn {
1277
+ task : : yield( ) ;
1278
+ fail ! ( ) ;
1279
+ }
1280
+ }
1281
+ } ;
1282
+ assert ! ( result. is_err( ) ) ;
1283
+ }
1284
+ }
1285
+
1286
+ #[ test] #[ ignore( cfg( windows) ) ]
1287
+ fn test_indestructible( ) {
1288
+ use rt:: test:: { run_in_newsched_task, spawntask_try} ;
1289
+ do run_in_newsched_task {
1290
+ let result = do spawntask_try {
1291
+ let mut t = task( ) ;
1292
+ t. watched( ) ;
1293
+ t. supervised( ) ;
1294
+ t. indestructible( ) ;
1295
+ do t. spawn {
1296
+ let ( p1, _c1) = stream : : <( ) >( ) ;
1297
+ let ( p2, c2) = stream :: < ( ) > ( ) ;
1298
+ let ( p3, c3) = stream :: < ( ) > ( ) ;
1299
+ let mut t = task( ) ;
1300
+ t. unwatched( ) ;
1301
+ do t. spawn {
1302
+ do ( || {
1303
+ p1. recv( ) ; // would deadlock if not killed
1304
+ } ) . finally {
1305
+ c2. send( ( ) ) ;
1306
+ } ;
1307
+ }
1308
+ let mut t = task( ) ;
1309
+ t. unwatched( ) ;
1310
+ do t. spawn {
1311
+ p3. recv( ) ;
1312
+ task:: yield ( ) ;
1313
+ fail!( ) ;
1314
+ }
1315
+ c3. send( ( ) ) ;
1316
+ p2. recv( ) ;
1317
+ }
1318
+ } ;
1319
+ assert ! ( result. is_ok( ) ) ;
1320
+ }
1321
+ }
0 commit comments