(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, timesuint, mut cur_taskBox<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_wakeBox<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_taskBox<Task>) { fail!() }
 74      fn maybe_yield(~self, _cur_taskBox<Task>) { fail!() }
 75      fn spawn_sibling(~self,
 76                       _cur_taskBox<Task>,
 77                       _optsTaskOpts,
 78                       _fproc():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  }