(index<- ) ./libgreen/simple.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
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 }