auto merge of #8677 : bblum/rust/scratch, r=alexcrichton

r anybody; there isn't anything complicated here
This commit is contained in:
bors 2013-08-23 00:16:28 -07:00
commit 5e5e2c71e4
7 changed files with 110 additions and 54 deletions

View file

@ -4814,9 +4814,13 @@ impl Resolver {
DontAllowCapturingSelf) {
Some(dl_def(def)) => return Some(def),
_ => {
self.session.span_bug(span,
"self wasn't mapped to a \
def?!")
if self.session.has_errors() {
// May happen inside a nested fn item, cf #6642.
return None;
} else {
self.session.span_bug(span,
"self wasn't mapped to a def?!")
}
}
}
}

View file

@ -50,6 +50,12 @@ impl<T> Cell<T> {
this.value.take_unwrap()
}
/// Yields the value if the cell is full, or `None` if it is empty.
pub fn take_opt(&self) -> Option<T> {
let this = unsafe { transmute_mut(self) };
this.value.take()
}
/// Returns the value, failing if the cell is full.
pub fn put_back(&self, value: T) {
let this = unsafe { transmute_mut(self) };

View file

@ -40,3 +40,39 @@ macro_rules! rtabort(
} )
)
macro_rules! assert_once_ever(
($( $msg:expr),+) => ( {
// FIXME(#8472) extra function should not be needed to hide unsafe
fn assert_once_ever() {
unsafe {
static mut already_happened: int = 0;
// Double-check lock to avoid a swap in the common case.
if already_happened != 0 ||
::unstable::intrinsics::atomic_xchg_relaxed(&mut already_happened, 1) != 0 {
fail!(fmt!("assert_once_ever happened twice: %s", fmt!($($msg),+)));
}
}
}
assert_once_ever();
} )
)
#[cfg(test)]
mod tests {
#[test]
fn test_assert_once_ever_ok() {
assert_once_ever!("help i'm stuck in an");
assert_once_ever!("assertion error message");
}
#[test] #[ignore(cfg(windows))] #[should_fail]
fn test_assert_once_ever_fail() {
use task;
fn f() { assert_once_ever!("if you're seeing this... good!") }
// linked & watched, naturally
task::spawn(f);
task::spawn(f);
}
}

View file

@ -499,13 +499,14 @@ impl<T> GenericPort<T> for Port<T> {
}
fn try_recv(&self) -> Option<T> {
let pone = self.next.take();
match pone.try_recv() {
Some(StreamPayload { val, next }) => {
self.next.put_back(next);
Some(val)
do self.next.take_opt().map_move_default(None) |pone| {
match pone.try_recv() {
Some(StreamPayload { val, next }) => {
self.next.put_back(next);
Some(val)
}
None => None
}
None => None
}
}
}

View file

@ -323,6 +323,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
// task tree, shut down the schedulers and set the exit code.
let handles = Cell::new(handles);
let on_exit: ~fn(bool) = |exit_success| {
assert_once_ever!("last task exiting");
let mut handles = handles.take();
for handle in handles.mut_iter() {

View file

@ -446,8 +446,7 @@ fn taskgroup_key() -> local_data::Key<@@mut Taskgroup> {
// Transitionary.
struct RuntimeGlue;
impl RuntimeGlue {
fn kill_task(handle: KillHandle) {
let mut handle = handle;
fn kill_task(mut handle: KillHandle) {
do handle.kill().map_move |killed_task| {
let killed_task = Cell::new(killed_task);
do Local::borrow::<Scheduler, ()> |sched| {
@ -457,44 +456,38 @@ impl RuntimeGlue {
}
fn with_task_handle_and_failing(blk: &fn(&KillHandle, bool)) {
if in_green_task_context() {
unsafe {
// Can't use safe borrow, because the taskgroup destructor needs to
// access the scheduler again to send kill signals to other tasks.
let me = Local::unsafe_borrow::<Task>();
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
}
} else {
rtabort!("task dying in bad context")
rtassert!(in_green_task_context());
unsafe {
// Can't use safe borrow, because the taskgroup destructor needs to
// access the scheduler again to send kill signals to other tasks.
let me = Local::unsafe_borrow::<Task>();
blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding)
}
}
fn with_my_taskgroup<U>(blk: &fn(&Taskgroup) -> U) -> U {
if in_green_task_context() {
unsafe {
// Can't use safe borrow, because creating new hashmaps for the
// tasksets requires an rng, which needs to borrow the sched.
let me = Local::unsafe_borrow::<Task>();
blk(match (*me).taskgroup {
None => {
// First task in its (unlinked/unsupervised) taskgroup.
// Lazily initialize.
let mut members = TaskSet::new();
let my_handle = (*me).death.kill_handle.get_ref().clone();
members.insert(my_handle);
let tasks = Exclusive::new(Some(TaskGroupData {
members: members,
descendants: TaskSet::new(),
}));
let group = Taskgroup(tasks, AncestorList(None), None);
(*me).taskgroup = Some(group);
(*me).taskgroup.get_ref()
}
Some(ref group) => group,
})
}
} else {
rtabort!("spawning in bad context")
rtassert!(in_green_task_context());
unsafe {
// Can't use safe borrow, because creating new hashmaps for the
// tasksets requires an rng, which needs to borrow the sched.
let me = Local::unsafe_borrow::<Task>();
blk(match (*me).taskgroup {
None => {
// First task in its (unlinked/unsupervised) taskgroup.
// Lazily initialize.
let mut members = TaskSet::new();
let my_handle = (*me).death.kill_handle.get_ref().clone();
members.insert(my_handle);
let tasks = Exclusive::new(Some(TaskGroupData {
members: members,
descendants: TaskSet::new(),
}));
let group = Taskgroup(tasks, AncestorList(None), None);
(*me).taskgroup = Some(group);
(*me).taskgroup.get_ref()
}
Some(ref group) => group,
})
}
}
}
@ -567,17 +560,11 @@ fn enlist_many(child: &KillHandle, child_arc: &TaskGroupArc,
result
}
pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
if in_green_task_context() {
spawn_raw_newsched(opts, f)
} else {
fail!("can't spawn from this context")
}
}
fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
pub fn spawn_raw(mut opts: TaskOpts, f: ~fn()) {
use rt::sched::*;
rtassert!(in_green_task_context());
let child_data = Cell::new(gen_child_taskgroup(opts.linked, opts.supervised));
let indestructible = opts.indestructible;

View file

@ -0,0 +1,21 @@
// Copyright 2013 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.
struct A;
impl A {
fn m(&self) {
fn x() {
self.m()
//~^ ERROR can't capture dynamic environment in a fn item
//~^^ ERROR `self` is not allowed in this context
}
}
}
fn main() {}