@@ -144,12 +144,12 @@ type sched_opts = {
144
144
*
145
145
* # Fields
146
146
*
147
- * * linked - Do not propagate failure to the parent task
147
+ * * linked - Propagate failure bidirectionally between child and parent.
148
+ * True by default. If both this and 'supervised' are false, then
149
+ * either task's failure will not affect the other ("unlinked").
148
150
*
149
- * All tasks are linked together via a tree, from parents to children. By
150
- * default children are 'supervised' by their parent and when they fail
151
- * so too will their parents. Settings this flag to false disables that
152
- * behavior.
151
+ * * supervised - Propagate failure unidirectionally from parent to child,
152
+ * but not from child to parent. False by default.
153
153
*
154
154
* * notify_chan - Enable lifecycle notifications on the given channel
155
155
*
@@ -168,7 +168,7 @@ type sched_opts = {
168
168
*/
169
169
type task_opts = {
170
170
linked : bool ,
171
- parented : bool ,
171
+ supervised : bool ,
172
172
notify_chan : option < comm:: chan < notification > > ,
173
173
sched : option < sched_opts > ,
174
174
} ;
@@ -237,7 +237,7 @@ impl task_builder for task_builder {
237
237
*/
238
238
fn supervised ( ) -> task_builder {
239
239
task_builder ( {
240
- opts : { linked : false , parented : true with self . opts } ,
240
+ opts : { linked : false , supervised : true with self . opts } ,
241
241
can_not_copy: none,
242
242
with * self . consume ( )
243
243
} )
@@ -248,7 +248,7 @@ impl task_builder for task_builder {
248
248
*/
249
249
fn linked ( ) -> task_builder {
250
250
task_builder ( {
251
- opts : { linked : true , parented : false with self . opts } ,
251
+ opts : { linked : true , supervised : false with self . opts } ,
252
252
can_not_copy: none,
253
253
with * self . consume ( )
254
254
} )
@@ -342,9 +342,7 @@ impl task_builder for task_builder {
342
342
fn spawn_with < A : send > ( +arg : A , +f : fn ~( +A ) ) {
343
343
let arg = ~mut some ( arg) ;
344
344
do self. spawn {
345
- let mut my_arg = none;
346
- my_arg <-> * arg;
347
- f ( option:: unwrap ( my_arg) )
345
+ f ( option:: swap_unwrap ( arg) )
348
346
}
349
347
}
350
348
@@ -385,7 +383,7 @@ fn default_task_opts() -> task_opts {
385
383
386
384
{
387
385
linked: true,
388
- parented : false ,
386
+ supervised : false ,
389
387
notify_chan: none,
390
388
sched: none
391
389
}
@@ -599,14 +597,14 @@ unsafe fn atomically<U>(f: fn() -> U) -> U {
599
597
*
600
598
* (2) The "tcb" is a per-task control structure that tracks a task's spawn
601
599
* configuration. It contains a reference to its taskgroup_arc, a
602
- * a reference to its node in the ancestor list (below), a flag for
600
+ * reference to its node in the ancestor list (below), a flag for
603
601
* whether it's part of the 'main'/'root' taskgroup, and an optionally
604
602
* configured notification port. These are stored in TLS.
605
603
*
606
604
* (3) The "ancestor_list" is a cons-style list of arc::exclusives which
607
605
* tracks 'generations' of taskgroups -- a group's ancestors are groups
608
606
* which (directly or transitively) spawn_supervised-ed them. Each task
609
- * recorded in the 'descendants' of each of its ancestor groups.
607
+ * is recorded in the 'descendants' of each of its ancestor groups.
610
608
*
611
609
* Spawning a supervised task is O(n) in the number of generations still
612
610
* alive, and exiting (by success or failure) that task is also O(n).
@@ -753,8 +751,7 @@ fn each_ancestor(list: &mut ancestor_list,
753
751
forward_blk : fn ( taskgroup_inner ) -> bool ,
754
752
last_generation : uint ) -> bool {
755
753
// Need to swap the list out to use it, to appease borrowck.
756
- let mut tmp_list = ancestor_list ( none) ;
757
- * list <-> tmp_list;
754
+ let tmp_list = util:: replace ( list, ancestor_list ( none) ) ;
758
755
let ( coalesce_this, early_break) =
759
756
iterate ( tmp_list, bail_opt, forward_blk, last_generation) ;
760
757
// What should our next ancestor end up being?
@@ -841,9 +838,9 @@ fn each_ancestor(list: &mut ancestor_list,
841
838
need_unwind = need_unwind || !do_continue;
842
839
// Tell caller whether or not to coalesce and/or unwind
843
840
if nobe_is_dead {
844
- let mut rest = ancestor_list ( none) ;
845
841
// Swap the list out here; the caller replaces us with it.
846
- nobe. ancestors <-> rest;
842
+ let rest = util:: replace ( & mut nobe. ancestors ,
843
+ ancestor_list ( none) ) ;
847
844
( some ( rest) , need_unwind)
848
845
} else {
849
846
( none, need_unwind)
@@ -854,11 +851,8 @@ fn each_ancestor(list: &mut ancestor_list,
854
851
// Wrapper around exclusive::with that appeases borrowck.
855
852
fn with_parent_tg < U > ( parent_group : & mut option < taskgroup_arc > ,
856
853
blk : fn ( taskgroup_inner ) -> U ) -> U {
857
- let mut tmp = none;
858
- * parent_group <-> tmp;
859
854
// If this trips, more likely the problem is 'blk' failed inside.
860
- assert tmp. is_some ( ) ;
861
- let tmp_arc = option:: unwrap ( tmp) ;
855
+ let tmp_arc = option:: swap_unwrap ( parent_group) ;
862
856
let result = do access_group ( tmp_arc) |tg_opt| { blk ( tg_opt) } ;
863
857
* parent_group <- some ( tmp_arc) ;
864
858
result
@@ -923,8 +917,7 @@ class auto_notify {
923
917
924
918
fn enlist_in_taskgroup ( state: taskgroup_inner, me: * rust_task,
925
919
is_member: bool ) -> bool {
926
- let mut newstate = none;
927
- * state <-> newstate;
920
+ let newstate = util:: replace ( state, none) ;
928
921
// If 'none', the group was failing. Can't enlist.
929
922
if newstate. is_some ( ) {
930
923
let group = option:: unwrap ( newstate) ;
@@ -939,8 +932,7 @@ fn enlist_in_taskgroup(state: taskgroup_inner, me: *rust_task,
939
932
940
933
// NB: Runs in destructor/post-exit context. Can't 'fail'.
941
934
fn leave_taskgroup ( state : taskgroup_inner , me : * rust_task , is_member : bool ) {
942
- let mut newstate = none;
943
- * state <-> newstate;
935
+ let newstate = util:: replace ( state, none) ;
944
936
// If 'none', already failing and we've already gotten a kill signal.
945
937
if newstate. is_some ( ) {
946
938
let group = option:: unwrap ( newstate) ;
@@ -960,8 +952,7 @@ fn kill_taskgroup(state: taskgroup_inner, me: *rust_task, is_main: bool) {
960
952
// so if we're failing, all concurrently exiting tasks must wait for us.
961
953
// To do it differently, we'd have to use the runtime's task refcounting,
962
954
// but that could leave task structs around long after their task exited.
963
- let mut newstate = none;
964
- * state <-> newstate;
955
+ let newstate = util:: replace ( state, none) ;
965
956
// Might already be none, if somebody is failing simultaneously.
966
957
// That's ok; only one task needs to do the dirty work. (Might also
967
958
// see 'none' if somebody already failed and we got a kill signal.)
@@ -1059,8 +1050,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
1059
1050
// alt ancestors
1060
1051
// some(ancestor_arc) { ancestor_list(some(ancestor_arc.clone())) }
1061
1052
// none { ancestor_list(none) }
1062
- let mut tmp = none;
1063
- * * ancestors <-> tmp;
1053
+ let tmp = util:: replace ( & mut * * ancestors, none) ;
1064
1054
if tmp. is_some ( ) {
1065
1055
let ancestor_arc = option:: unwrap ( tmp) ;
1066
1056
let result = ancestor_arc. clone ( ) ;
@@ -1074,16 +1064,14 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
1074
1064
1075
1065
fn spawn_raw ( opts : task_opts , +f : fn ~( ) ) {
1076
1066
let ( child_tg, ancestors, is_main) =
1077
- gen_child_taskgroup ( opts. linked , opts. parented ) ;
1067
+ gen_child_taskgroup ( opts. linked , opts. supervised ) ;
1078
1068
1079
1069
unsafe {
1080
- let child_data_ptr = ~mut some ( ( child_tg, ancestors, f) ) ;
1070
+ let child_data = ~mut some ( ( child_tg, ancestors, f) ) ;
1081
1071
// Being killed with the unsafe task/closure pointers would leak them.
1082
1072
do unkillable {
1083
1073
// Agh. Get move-mode items into the closure. FIXME (#2829)
1084
- let mut child_data = none;
1085
- * child_data_ptr <-> child_data;
1086
- let ( child_tg, ancestors, f) = option:: unwrap ( child_data) ;
1074
+ let ( child_tg, ancestors, f) = option:: swap_unwrap ( child_data) ;
1087
1075
// Create child task.
1088
1076
let new_task = alt opts. sched {
1089
1077
none { rustrt : : new_task ( ) }
@@ -1116,12 +1104,10 @@ fn spawn_raw(opts: task_opts, +f: fn~()) {
1116
1104
-ancestors : ancestor_list , is_main : bool ,
1117
1105
notify_chan : option < comm:: chan < notification > > ,
1118
1106
-f : fn ~( ) ) -> fn ~( ) {
1119
- let child_tg_ptr = ~mut some ( ( child_arc, ancestors) ) ;
1107
+ let child_data = ~mut some ( ( child_arc, ancestors) ) ;
1120
1108
return fn ~( ) {
1121
1109
// Agh. Get move-mode items into the closure. FIXME (#2829)
1122
- let mut tg_data_opt = none;
1123
- * child_tg_ptr <-> tg_data_opt;
1124
- let mut ( child_arc, ancestors) = option:: unwrap ( tg_data_opt) ;
1110
+ let mut ( child_arc, ancestors) = option:: swap_unwrap ( child_data) ;
1125
1111
// Child task runs this code.
1126
1112
1127
1113
// Even if the below code fails to kick the child off, we must
@@ -1528,7 +1514,7 @@ fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
1528
1514
// they don't make sense (redundant with task().supervised()).
1529
1515
let b0 = task ( ) ;
1530
1516
let b1 = task_builder ( {
1531
- opts : { linked : true , parented : true with b0. opts } ,
1517
+ opts : { linked : true , supervised : true with b0. opts } ,
1532
1518
can_not_copy: none,
1533
1519
with * b0
1534
1520
} ) ;
@@ -1541,7 +1527,7 @@ fn test_spawn_linked_sup_fail_down() { // parent fails; child fails
1541
1527
// they don't make sense (redundant with task().supervised()).
1542
1528
let b0 = task ( ) ;
1543
1529
let b1 = task_builder ( {
1544
- opts : { linked : true , parented : true with b0. opts } ,
1530
+ opts : { linked : true , supervised : true with b0. opts } ,
1545
1531
can_not_copy: none,
1546
1532
with * b0
1547
1533
} ) ;
0 commit comments