@@ -585,11 +585,67 @@ unsafe fn atomically<U>(f: fn() -> U) -> U {
585
585
}
586
586
587
587
/****************************************************************************
588
- * Internal
588
+ * Spawning & linked failure
589
+ *
590
+ * Several data structures are involved in task management to allow properly
591
+ * propagating failure across linked/supervised tasks.
592
+ *
593
+ * (1) The "taskgroup_arc" is an arc::exclusive which contains a hashset of
594
+ * all tasks that are part of the group. Some tasks are 'members', which
595
+ * means if they fail, they will kill everybody else in the taskgroup.
596
+ * Other tasks are 'descendants', which means they will not kill tasks
597
+ * from this group, but can be killed by failing members.
598
+ *
599
+ * A new one of these is created each spawn_linked or spawn_supervised.
600
+ *
601
+ * (2) The "taskgroup" is a per-task control structure that tracks a task's
602
+ * spawn configuration. It contains a reference to its taskgroup_arc,
603
+ * a reference to its node in the ancestor list (below), a flag for
604
+ * whether it's part of the 'main'/'root' taskgroup, and an optionally
605
+ * configured notification port. These are stored in TLS.
606
+ *
607
+ * (3) The "ancestor_list" is a cons-style list of arc::exclusives which
608
+ * tracks 'generations' of taskgroups -- a group's ancestors are groups
609
+ * which (directly or transitively) spawn_supervised-ed them. Each task
610
+ * recorded in the 'descendants' of each of its ancestor groups.
611
+ *
612
+ * Spawning a supervised task is O(n) in the number of generations still
613
+ * alive, and exiting (by success or failure) that task is also O(n).
614
+ *
615
+ * This diagram depicts the references between these data structures:
616
+ *
617
+ * linked_________________________________
618
+ * ___/ _________ \___
619
+ * / \ | group X | / \
620
+ * ( A ) - - - - - - - > | {A,B} {}|< - - -( B )
621
+ * \___/ |_________| \___/
622
+ * unlinked
623
+ * | __ (nil)
624
+ * | //| The following code causes this:
625
+ * |__ // /\ _________
626
+ * / \ // || | group Y | fn taskA() {
627
+ * ( C )- - - ||- - - > |{C} {D,E}| spawn(taskB);
628
+ * \___/ / \=====> |_________| spawn_unlinked(taskC);
629
+ * supervise /gen \ ...
630
+ * | __ \ 00 / }
631
+ * | //| \__/ fn taskB() { ... }
632
+ * |__ // /\ _________ fn taskC() {
633
+ * / \/ || | group Z | spawn_supervised(taskD);
634
+ * ( D )- - - ||- - - > | {D} {E} | ...
635
+ * \___/ / \=====> |_________| }
636
+ * supervise /gen \ fn taskD() {
637
+ * | __ \ 01 / spawn_supervised(taskE);
638
+ * | //| \__/ ...
639
+ * |__ // _________ }
640
+ * / \/ | group W | fn taskE() { ... }
641
+ * ( E )- - - - - - - > | {E} {} |
642
+ * \___/ |_________|
643
+ *
644
+ * "taskgroup" "taskgroup_arc"
645
+ * "ancestor_list"
646
+ *
589
647
****************************************************************************/
590
648
591
- /* spawning */
592
-
593
649
type sched_id = int ;
594
650
type task_id = int ;
595
651
@@ -598,8 +654,6 @@ type task_id = int;
598
654
type rust_task = libc:: c_void ;
599
655
type rust_closure = libc:: c_void ;
600
656
601
- /* linked failure */
602
-
603
657
type taskset = send_map:: linear:: linear_map < * rust_task , ( ) > ;
604
658
605
659
fn new_taskset ( ) -> taskset {
0 commit comments