about summary refs log tree commit diff
path: root/src/libcore/task.rs
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2012-08-01 23:01:50 -0400
committerBen Blum <bblum@andrew.cmu.edu>2012-08-01 23:08:06 -0400
commitac0c8b08233b8654aa69a0902bacd7be40072c54 (patch)
tree5f1bf8a065cbf8d3d4f2a0ef84ebac1a856e7731 /src/libcore/task.rs
parent7cb3f3e86a5500ecf40500dc9f6cedabd8e0349e (diff)
Linked failure: add ASCII art. Close #1868.
Diffstat (limited to 'src/libcore/task.rs')
-rw-r--r--src/libcore/task.rs64
1 files changed, 59 insertions, 5 deletions
diff --git a/src/libcore/task.rs b/src/libcore/task.rs
index 08ac52e44ff..8606d2f89f8 100644
--- a/src/libcore/task.rs
+++ b/src/libcore/task.rs
@@ -585,11 +585,67 @@ unsafe fn atomically<U>(f: fn() -> U) -> U {
 }
 
 /****************************************************************************
- * Internal
+ * Spawning & linked failure
+ *
+ * Several data structures are involved in task management to allow properly
+ * propagating failure across linked/supervised tasks.
+ *
+ * (1) The "taskgroup_arc" is an arc::exclusive which contains a hashset of
+ *     all tasks that are part of the group. Some tasks are 'members', which
+ *     means if they fail, they will kill everybody else in the taskgroup.
+ *     Other tasks are 'descendants', which means they will not kill tasks
+ *     from this group, but can be killed by failing members.
+ *
+ *     A new one of these is created each spawn_linked or spawn_supervised.
+ *
+ * (2) The "taskgroup" is a per-task control structure that tracks a task's
+ *     spawn configuration. It contains a reference to its taskgroup_arc,
+ *     a reference to its node in the ancestor list (below), a flag for
+ *     whether it's part of the 'main'/'root' taskgroup, and an optionally
+ *     configured notification port. These are stored in TLS.
+ *
+ * (3) The "ancestor_list" is a cons-style list of arc::exclusives which
+ *     tracks 'generations' of taskgroups -- a group's ancestors are groups
+ *     which (directly or transitively) spawn_supervised-ed them. Each task
+ *     recorded in the 'descendants' of each of its ancestor groups.
+ *
+ *     Spawning a supervised task is O(n) in the number of generations still
+ *     alive, and exiting (by success or failure) that task is also O(n).
+ *
+ * This diagram depicts the references between these data structures:
+ *
+ *          linked_________________________________
+ *        ___/                   _________         \___
+ *       /   \                  | group X |        /   \
+ *      (  A  ) - - - - - - - > | {A,B} {}|< - - -(  B  )
+ *       \___/                  |_________|        \___/
+ *      unlinked
+ *         |      __ (nil)
+ *         |      //|                         The following code causes this:
+ *         |__   //   /\         _________
+ *        /   \ //    ||        | group Y |     fn taskA() {
+ *       (  C  )- - - ||- - - > |{C} {D,E}|         spawn(taskB);
+ *        \___/      /  \=====> |_________|         spawn_unlinked(taskC);
+ *      supervise   /gen \                          ...
+ *         |    __  \ 00 /                      }
+ *         |    //|  \__/                       fn taskB() { ... }
+ *         |__ //     /\         _________      fn taskC() {
+ *        /   \/      ||        | group Z |         spawn_supervised(taskD);
+ *       (  D  )- - - ||- - - > | {D} {E} |         ...
+ *        \___/      /  \=====> |_________|     }
+ *      supervise   /gen \                      fn taskD() {
+ *         |    __  \ 01 /                          spawn_supervised(taskE);
+ *         |    //|  \__/                           ...
+ *         |__ //                _________      }
+ *        /   \/                | group W |     fn taskE() { ... }
+ *       (  E  )- - - - - - - > | {E}  {} |
+ *        \___/                 |_________|
+ *
+ *     "taskgroup"            "taskgroup_arc"
+ *              "ancestor_list"
+ *
  ****************************************************************************/
 
-/* spawning */
-
 type sched_id = int;
 type task_id = int;
 
@@ -598,8 +654,6 @@ type task_id = int;
 type rust_task = libc::c_void;
 type rust_closure = libc::c_void;
 
-/* linked failure */
-
 type taskset = send_map::linear::linear_map<*rust_task,()>;
 
 fn new_taskset() -> taskset {