6 An executing Rust program consists of a tree of tasks, each with their own
7 stack, and sole ownership of their allocated heap data. Tasks communicate
8 with each other using ports and channels.
10 When a task fails, that failure will propagate to its parent (the task
11 that spawned it) and the parent will fail as well. The reverse is not
12 true: when a parent task fails its children will continue executing. When
13 the root (main) task fails, all tasks fail, and then so does the entire
16 A task may remove itself from this failure propagation mechanism by
17 calling the <unsupervise> function, after which failure will only
18 result in the termination of that task.
20 Tasks may execute in parallel and are scheduled automatically by the runtime.
25 > log(debug, "Hello, World!");
29 import cast = unsafe::reinterpret_cast;
38 export task_notification;
48 export spawn_joinable;
50 #[abi = "rust-intrinsic"]
52 // these must run on the Rust stack so that they can swap stacks etc:
53 fn task_sleep(task: *rust_task, time_in_us: uint, &killed: bool);
57 fnptr: c::intptr_t, envptr: c::intptr_t
60 #[link_name = "rustrt"]
63 // these can run on the C stack:
66 fn get_task_id() -> task_id;
67 fn rust_get_task() -> *rust_task;
69 fn new_task() -> task_id;
70 fn drop_task(task_id: *rust_task);
71 fn get_task_pointer(id: task_id) -> *rust_task;
73 fn migrate_alloc(alloc: *u8, target: task_id);
75 fn start_task(id: task, closure: *rust_closure);
82 mutable notify_enabled: int,
83 mutable notify_chan: comm::chan<task_notification>,
84 mutable stack_ptr: *u8};
86 resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }
100 Creates and executes a new child task
102 Sets up a new task with its own call stack and schedules it to be
103 executed. Upon execution, the closure `f()` will be invoked.
107 f - A function to execute in the new task
111 A handle to the new task
113 fn spawn(-f: sendfn()) -> task {
117 fn spawn_inner(-f: sendfn(),
118 notify: option<comm::chan<task_notification>>) -> task unsafe {
119 let closure: *rust_closure = unsafe::reinterpret_cast(ptr::addr_of(f));
120 #debug("spawn: closure={%x,%x}", (*closure).fnptr, (*closure).envptr);
121 let id = rustrt::new_task();
123 // set up notifications if they are enabled.
124 option::may(notify) {|c|
125 let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));
126 (**task_ptr).notify_enabled = 1;
127 (**task_ptr).notify_chan = c;
130 rustrt::start_task(id, closure);
138 A task that sends notification upon termination
140 type joinable_task = (task, comm::port<task_notification>);
142 fn spawn_joinable(-f: sendfn()) -> joinable_task {
143 let notify_port = comm::port();
144 let notify_chan = comm::chan(notify_port);
145 let task = spawn_inner(f, some(notify_chan));
146 ret (task, notify_port);
148 resource notify_rsrc(data: (comm::chan<task_notification>,
150 @mutable task_result)) {
151 let (chan, task, tr) = data;
152 let msg = exit(task, *tr);
153 comm::send(chan, msg);
156 let notify_port = comm::port();
157 let notify_chan = comm::chan(notify_port);
158 let g = sendfn[copy notify_chan; move f]() {
159 let this_task = rustrt::get_task_id();
160 let result = @mutable tr_failure;
161 let _rsrc = notify_rsrc((notify_chan, this_task, result));
163 *result = tr_success; // rsrc will fire msg when fn returns
166 ret (task, notify_port);
173 Indicates the manner in which a task exited
176 /* Variant: tr_success */
178 /* Variant: tr_failure */
183 Tag: task_notification
185 Message sent upon task exit to indicate normal or abnormal termination
187 tag task_notification {
189 exit(task, task_result);
192 /* Section: Operations */
197 Retreives a handle to the currently executing task
199 fn get_task() -> task { rustrt::get_task_id() }
204 Hints the scheduler to yield this task for a specified ammount of time.
208 time_in_us - maximum number of microseconds to yield control for
210 fn sleep(time_in_us: uint) {
211 let task = rustrt::rust_get_task();
213 // FIXME: uncomment this when extfmt is moved to core
215 // #debug("yielding for %u us", time_in_us);
216 rusti::task_sleep(task, time_in_us, killed);
225 Yield control to the task scheduler
227 The scheduler may schedule another task to execute.
229 fn yield() { sleep(1u) }
234 Wait for a child task to exit
236 The child task must have been spawned with <spawn_joinable>, which
237 produces a notification port that the child uses to communicate its
242 A task_result indicating whether the task terminated normally or failed
244 fn join(task_port: joinable_task) -> task_result {
245 let (id, port) = task_port;
246 alt comm::recv::<task_notification>(port) {
251 // FIXME: uncomment this when extfmt is moved to core
253 // fail #fmt["join received id %d, expected %d", _id, id]
261 Function: unsupervise
263 Detaches this task from its parent in the task tree
265 An unsupervised task will not propagate its failure up the task tree
267 fn unsupervise() { ret sys::unsupervise(); }
272 Pins the current task and future child tasks to a single scheduler thread
274 fn pin() { rustrt::pin_task(); }
279 Unpin the current task and future child tasks
281 fn unpin() { rustrt::unpin_task(); }
286 // indent-tabs-mode: nil
288 // buffer-file-coding-system: utf-8-unix