f: proc():Send) {
self.put_task(cur_task);
+ // First, set up a bomb which when it goes off will restore the local
+ // task unless its disarmed. This will allow us to gracefully fail from
+ // inside of `configure` which allocates a new task.
+ struct Bomb { inner: Option<Box<GreenTask>> }
+ impl Drop for Bomb {
+ fn drop(&mut self) {
+ let _ = self.inner.take().map(|task| task.put());
+ }
+ }
+ let mut bomb = Bomb { inner: Some(self) };
+
// Spawns a task into the current scheduler. We allocate the new task's
// stack from the scheduler's stack pool, and then configure it
// accordingly to `opts`. Afterwards we bootstrap it immediately by
// switching to it.
//
// Upon returning, our task is back in TLS and we're good to return.
- let mut sched = self.sched.take_unwrap();
- let sibling = GreenTask::configure(&mut sched.stack_pool, opts, f);
- sched.run_task(self, sibling)
+ let sibling = {
+ let sched = bomb.inner.get_mut_ref().sched.get_mut_ref();
+ GreenTask::configure(&mut sched.stack_pool, opts, f)
+ };
+ let mut me = bomb.inner.take().unwrap();
+ let sched = me.sched.take().unwrap();
+ sched.run_task(me, sibling)
}
// Local I/O is provided by the scheduler's event loop
static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
static mut TASK_LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
-pub struct Token(());
+pub struct Token { _private: () }
impl Drop for Token {
fn drop(&mut self) { decrement() }
/// the count when dropped.
pub fn increment() -> Token {
let _ = unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst) };
- Token(())
+ Token { _private: () }
}
pub fn decrement() {
fn block_and_wake() {
let task = box Task::new();
let mut task = BlockedTask::block(task).wake().unwrap();
- task.destroy();
+ task.drop();
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-macos apparently gargantuan mmap requests are ok?
+
+#![feature(phase)]
+
+#[phase(plugin)]
+extern crate green;
+extern crate native;
+
+use std::task::TaskBuilder;
+use native::NativeTaskBuilder;
+
+green_start!(main)
+
+fn main() {
+ test();
+
+ let (tx, rx) = channel();
+ TaskBuilder::new().native().spawn(proc() {
+ tx.send(test());
+ });
+ rx.recv();
+}
+
+#[cfg(not(target_word_size = "64"))]
+fn test() {}
+
+#[cfg(target_word_size = "64")]
+fn test() {
+ let (tx, rx) = channel();
+ spawn(proc() {
+ TaskBuilder::new().stack_size(1024 * 1024 * 1024 * 64).spawn(proc() {
+ });
+ tx.send(());
+ });
+
+ assert!(rx.recv_opt().is_err());
+}