]> git.lizzy.rs Git - rust.git/blob - src/libgreen/simple.rs
auto merge of #13967 : richo/rust/features/ICE-fails, r=alexcrichton
[rust.git] / src / libgreen / simple.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! A small module implementing a simple "runtime" used for bootstrapping a rust
12 //! scheduler pool and then interacting with it.
13
14 use std::any::Any;
15 use std::cast;
16 use std::rt::Runtime;
17 use std::rt::local::Local;
18 use std::rt::rtio;
19 use std::rt::task::{Task, BlockedTask};
20 use std::task::TaskOpts;
21 use std::unstable::mutex::NativeMutex;
22
23 struct SimpleTask {
24     lock: NativeMutex,
25     awoken: bool,
26 }
27
28 impl Runtime for SimpleTask {
29     // Implement the simple tasks of descheduling and rescheduling, but only in
30     // a simple number of cases.
31     fn deschedule(mut ~self, times: uint, mut cur_task: Box<Task>,
32                   f: |BlockedTask| -> Result<(), BlockedTask>) {
33         assert!(times == 1);
34
35         let me = &mut *self as *mut SimpleTask;
36         let cur_dupe = &*cur_task as *Task;
37         cur_task.put_runtime(self);
38         let task = BlockedTask::block(cur_task);
39
40         // See libnative/task.rs for what's going on here with the `awoken`
41         // field and the while loop around wait()
42         unsafe {
43             let guard = (*me).lock.lock();
44             (*me).awoken = false;
45             match f(task) {
46                 Ok(()) => {
47                     while !(*me).awoken {
48                         guard.wait();
49                     }
50                 }
51                 Err(task) => { cast::forget(task.wake()); }
52             }
53             drop(guard);
54             cur_task = cast::transmute(cur_dupe);
55         }
56         Local::put(cur_task);
57     }
58     fn reawaken(mut ~self, mut to_wake: Box<Task>) {
59         let me = &mut *self as *mut SimpleTask;
60         to_wake.put_runtime(self);
61         unsafe {
62             cast::forget(to_wake);
63             let guard = (*me).lock.lock();
64             (*me).awoken = true;
65             guard.signal();
66         }
67     }
68
69     // These functions are all unimplemented and fail as a result. This is on
70     // purpose. A "simple task" is just that, a very simple task that can't
71     // really do a whole lot. The only purpose of the task is to get us off our
72     // feet and running.
73     fn yield_now(~self, _cur_task: Box<Task>) { fail!() }
74     fn maybe_yield(~self, _cur_task: Box<Task>) { fail!() }
75     fn spawn_sibling(~self,
76                      _cur_task: Box<Task>,
77                      _opts: TaskOpts,
78                      _f: proc():Send) {
79         fail!()
80     }
81     fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
82     fn stack_bounds(&self) -> (uint, uint) { fail!() }
83     fn can_block(&self) -> bool { true }
84     fn wrap(~self) -> Box<Any> { fail!() }
85 }
86
87 pub fn task() -> Box<Task> {
88     let mut task = box Task::new();
89     task.put_runtime(box SimpleTask {
90         lock: unsafe {NativeMutex::new()},
91         awoken: false,
92     });
93     return task;
94 }