diff --git a/src/libextra/comm.rs b/src/libextra/comm.rs index 44581efc6f07b..776e25cac8908 100644 --- a/src/libextra/comm.rs +++ b/src/libextra/comm.rs @@ -18,9 +18,8 @@ Higher level communication abstractions. use std::comm::{GenericChan, GenericSmartChan, GenericPort}; -use std::comm::{Chan, Port, Selectable, Peekable}; +use std::comm::{Chan, Port, Peekable}; use std::comm; -use std::pipes; /// An extension of `pipes::stream` that allows both sending and receiving. pub struct DuplexStream { @@ -75,12 +74,6 @@ impl Peekable for DuplexStream { } } -impl Selectable for DuplexStream { - fn header(&mut self) -> *mut pipes::PacketHeader { - self.port.header() - } -} - /// Creates a bidirectional stream. pub fn DuplexStream() -> (DuplexStream, DuplexStream) diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index a0731dc3494c2..4356f1143da46 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -14,7 +14,6 @@ Message passing #[allow(missing_doc)]; -use cast::transmute; use either::{Either, Left, Right}; use kinds::Send; use option::{Option, Some}; @@ -23,12 +22,6 @@ pub use rt::comm::SendDeferred; use rtcomm = rt::comm; use rt; -use pipes::{wait_many, PacketHeader}; - -// FIXME #5160: Making this public exposes some plumbing from -// pipes. Needs some refactoring -pub use pipes::Selectable; - /// A trait for things that can send multiple messages. pub trait GenericChan { /// Sends a message. @@ -146,15 +139,6 @@ impl Peekable for Port { } } -impl Selectable for Port { - fn header(&mut self) -> *mut PacketHeader { - match self.inner { - Left(ref mut port) => port.header(), - Right(_) => fail!("can't select on newsched ports") - } - } -} - /// A channel that can be shared between many senders. pub struct SharedChan { inner: Either>, rtcomm::SharedChan> @@ -318,8 +302,8 @@ mod pipesy { use kinds::Send; use option::{Option, Some, None}; - use pipes::{recv, try_recv, peek, PacketHeader}; - use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable}; + use pipes::{recv, try_recv, peek}; + use super::{GenericChan, GenericSmartChan, GenericPort, Peekable}; use cast::transmute_mut; /*proto! oneshot ( @@ -651,80 +635,6 @@ mod pipesy { } } - impl Selectable for Port { - fn header(&mut self) -> *mut PacketHeader { - match self.endp { - Some(ref mut endp) => endp.header(), - None => fail!("peeking empty stream") - } - } -} - -} - -/// Returns the index of an endpoint that is ready to receive. -pub fn selecti(endpoints: &mut [T]) -> uint { - wait_many(endpoints) -} - -/// Returns 0 or 1 depending on which endpoint is ready to receive -pub fn select2i(a: &mut A, b: &mut B) - -> Either<(), ()> { - let mut endpoints = [ a.header(), b.header() ]; - match wait_many(endpoints) { - 0 => Left(()), - 1 => Right(()), - _ => fail!("wait returned unexpected index"), - } -} - -/// Receive a message from one of two endpoints. -pub trait Select2 { - /// Receive a message or return `None` if a connection closes. - fn try_select(&mut self) -> Either, Option>; - /// Receive a message or fail if a connection closes. - fn select(&mut self) -> Either; -} - -impl, - Right:Selectable + GenericPort> - Select2 - for (Left, Right) { - fn select(&mut self) -> Either { - // XXX: Bad borrow check workaround. - unsafe { - let this: &(Left, Right) = transmute(self); - match *this { - (ref lp, ref rp) => { - let lp: &mut Left = transmute(lp); - let rp: &mut Right = transmute(rp); - match select2i(lp, rp) { - Left(()) => Left(lp.recv()), - Right(()) => Right(rp.recv()), - } - } - } - } - } - - fn try_select(&mut self) -> Either, Option> { - // XXX: Bad borrow check workaround. - unsafe { - let this: &(Left, Right) = transmute(self); - match *this { - (ref lp, ref rp) => { - let lp: &mut Left = transmute(lp); - let rp: &mut Right = transmute(rp); - match select2i(lp, rp) { - Left(()) => Left (lp.try_recv()), - Right(()) => Right(rp.try_recv()), - } - } - } - } - } } #[cfg(test)] @@ -732,22 +642,6 @@ mod test { use either::Right; use super::{Chan, Port, oneshot, stream}; - #[test] - fn test_select2() { - let (p1, c1) = stream(); - let (p2, c2) = stream(); - - c1.send(~"abc"); - - let mut tuple = (p1, p2); - match tuple.select() { - Right(_) => fail!(), - _ => (), - } - - c2.send(123); - } - #[test] fn test_oneshot() { let (p, c) = oneshot(); diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs index 1fd534825a544..78f937e058a41 100644 --- a/src/libstd/pipes.rs +++ b/src/libstd/pipes.rs @@ -868,47 +868,3 @@ pub mod rt { pub fn make_some(val: T) -> Option { Some(val) } pub fn make_none() -> Option { None } } - -#[cfg(test)] -mod test { - use either::Right; - use comm::{Chan, Port, oneshot, recv_one, stream, Select2, - GenericChan, Peekable}; - - #[test] - fn test_select2() { - let (p1, c1) = stream(); - let (p2, c2) = stream(); - - c1.send(~"abc"); - - let mut tuple = (p1, p2); - match tuple.select() { - Right(_) => fail!(), - _ => (), - } - - c2.send(123); - } - - #[test] - fn test_oneshot() { - let (p, c) = oneshot(); - - c.send(()); - - recv_one(p) - } - - #[test] - fn test_peek_terminated() { - let (port, chan): (Port, Chan) = stream(); - - { - // Destroy the channel - let _chan = chan; - } - - assert!(!port.peek()); - } -} diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs index 7ab63233cff2f..131507196b1f2 100644 --- a/src/libstd/rt/local.rs +++ b/src/libstd/rt/local.rs @@ -126,6 +126,7 @@ impl Local for IoFactoryObject { #[cfg(test)] mod test { + use unstable::run_in_bare_thread; use rt::test::*; use super::*; use rt::task::Task; @@ -133,56 +134,64 @@ mod test { #[test] fn thread_local_task_smoke_test() { - local_ptr::init_tls_key(); - let mut sched = ~new_test_uv_sched(); - let task = ~Task::new_root(&mut sched.stack_pool, || {}); - Local::put(task); - let task: ~Task = Local::take(); - cleanup_task(task); + do run_in_bare_thread { + local_ptr::init_tls_key(); + let mut sched = ~new_test_uv_sched(); + let task = ~Task::new_root(&mut sched.stack_pool, || {}); + Local::put(task); + let task: ~Task = Local::take(); + cleanup_task(task); + } } #[test] fn thread_local_task_two_instances() { - local_ptr::init_tls_key(); - let mut sched = ~new_test_uv_sched(); - let task = ~Task::new_root(&mut sched.stack_pool, || {}); - Local::put(task); - let task: ~Task = Local::take(); - cleanup_task(task); - let task = ~Task::new_root(&mut sched.stack_pool, || {}); - Local::put(task); - let task: ~Task = Local::take(); - cleanup_task(task); + do run_in_bare_thread { + local_ptr::init_tls_key(); + let mut sched = ~new_test_uv_sched(); + let task = ~Task::new_root(&mut sched.stack_pool, || {}); + Local::put(task); + let task: ~Task = Local::take(); + cleanup_task(task); + let task = ~Task::new_root(&mut sched.stack_pool, || {}); + Local::put(task); + let task: ~Task = Local::take(); + cleanup_task(task); + } } #[test] fn borrow_smoke_test() { - local_ptr::init_tls_key(); - let mut sched = ~new_test_uv_sched(); - let task = ~Task::new_root(&mut sched.stack_pool, || {}); - Local::put(task); - - unsafe { - let _task: *mut Task = Local::unsafe_borrow(); + do run_in_bare_thread { + local_ptr::init_tls_key(); + let mut sched = ~new_test_uv_sched(); + let task = ~Task::new_root(&mut sched.stack_pool, || {}); + Local::put(task); + + unsafe { + let _task: *mut Task = Local::unsafe_borrow(); + } + let task: ~Task = Local::take(); + cleanup_task(task); } - let task: ~Task = Local::take(); - cleanup_task(task); } #[test] fn borrow_with_return() { - local_ptr::init_tls_key(); - let mut sched = ~new_test_uv_sched(); - let task = ~Task::new_root(&mut sched.stack_pool, || {}); - Local::put(task); - - let res = do Local::borrow:: |_task| { - true - }; - assert!(res) - let task: ~Task = Local::take(); - cleanup_task(task); + do run_in_bare_thread { + local_ptr::init_tls_key(); + let mut sched = ~new_test_uv_sched(); + let task = ~Task::new_root(&mut sched.stack_pool, || {}); + Local::put(task); + + let res = do Local::borrow:: |_task| { + true + }; + assert!(res) + let task: ~Task = Local::take(); + cleanup_task(task); + } } } diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs index cd7c5daa444d7..652e39b05c7e0 100644 --- a/src/libstd/rt/local_ptr.rs +++ b/src/libstd/rt/local_ptr.rs @@ -52,7 +52,9 @@ pub unsafe fn put(sched: ~T) { pub unsafe fn take() -> ~T { let key = tls_key(); let void_ptr: *mut c_void = tls::get(key); - rtassert!(void_ptr.is_not_null()); + if void_ptr.is_null() { + rtabort!("thread-local pointer is null. bogus!"); + } let ptr: ~T = cast::transmute(void_ptr); tls::set(key, ptr::mut_null()); return ptr; @@ -68,8 +70,8 @@ pub fn exists() -> bool { } } -/// Borrow the thread-local scheduler from thread-local storage. -/// While the scheduler is borrowed it is not available in TLS. +/// Borrow the thread-local value from thread-local storage. +/// While the value is borrowed it is not available in TLS. /// /// # Safety note /// @@ -88,21 +90,23 @@ pub unsafe fn borrow(f: &fn(&mut T)) { } } -/// Borrow a mutable reference to the thread-local Scheduler +/// Borrow a mutable reference to the thread-local value /// /// # Safety Note /// -/// Because this leaves the Scheduler in thread-local storage it is possible +/// Because this leaves the value in thread-local storage it is possible /// For the Scheduler pointer to be aliased pub unsafe fn unsafe_borrow() -> *mut T { let key = tls_key(); - let mut void_sched: *mut c_void = tls::get(key); - rtassert!(void_sched.is_not_null()); + let mut void_ptr: *mut c_void = tls::get(key); + if void_ptr.is_null() { + rtabort!("thread-local pointer is null. bogus!"); + } { - let sched: *mut *mut c_void = &mut void_sched; - let sched: *mut ~T = sched as *mut ~T; - let sched: *mut T = &mut **sched; - return sched; + let ptr: *mut *mut c_void = &mut void_ptr; + let ptr: *mut ~T = ptr as *mut ~T; + let ptr: *mut T = &mut **ptr; + return ptr; } } diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 4cfe0efacfefe..33e83fd904041 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -432,13 +432,3 @@ pub fn context() -> RuntimeContext { pub fn rust_try_get_task() -> *rust_task; } } - -#[test] -fn test_context() { - use unstable::run_in_bare_thread; - - assert_eq!(context(), OldTaskContext); - do run_in_bare_thread { - assert_eq!(context(), GlobalContext); - } -} diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 18cfeade157db..a5c8abc2a6c0e 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -172,6 +172,10 @@ impl Scheduler { rtdebug!("stopping scheduler %u", stask.sched.get_ref().sched_id()); + // Should not have any messages + let message = stask.sched.get_mut_ref().message_queue.pop(); + assert!(message.is_none()); + stask.destroyed = true; } @@ -336,11 +340,14 @@ impl Scheduler { match this.message_queue.pop() { Some(PinnedTask(task)) => { let mut task = task; + this.event_loop.callback(Scheduler::run_sched_once); task.give_home(Sched(this.make_handle())); this.resume_task_immediately(task); return None; } Some(TaskFromFriend(task)) => { + this.event_loop.callback(Scheduler::run_sched_once); + rtdebug!("got a task from a friend. lovely!"); return this.sched_schedule_task(task); } Some(Wake) => { @@ -395,6 +402,7 @@ impl Scheduler { /// Take a non-homed task we aren't allowed to run here and send /// it to the designated friend scheduler to execute. fn send_to_friend(&mut self, task: ~Task) { + rtdebug!("sending a task to friend"); match self.friend_handle { Some(ref mut handle) => { handle.send(TaskFromFriend(task)); @@ -426,12 +434,14 @@ impl Scheduler { Scheduler::send_task_home(task); return Some(this); } else { + this.event_loop.callback(Scheduler::run_sched_once); task.give_home(Sched(home_handle)); this.resume_task_immediately(task); return None; } } AnySched if this.run_anything => { + this.event_loop.callback(Scheduler::run_sched_once); task.give_home(AnySched); this.resume_task_immediately(task); return None; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index abafe1cf209c7..ffe9f118b477c 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -303,7 +303,7 @@ impl Task { impl Drop for Task { fn drop(&self) { rtdebug!("called drop for a task: %u", borrow::to_uint(self)); - assert!(self.destroyed) + rtassert!(self.destroyed) } } @@ -313,7 +313,7 @@ impl Drop for Task { impl Coroutine { pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine { - static MIN_STACK_SIZE: uint = 2000000; // XXX: Too much stack + static MIN_STACK_SIZE: uint = 3000000; // XXX: Too much stack let start = Coroutine::build_start_wrapper(start); let mut stack = stack_pool.take_segment(MIN_STACK_SIZE); diff --git a/src/test/run-pass/issue-3176.rs b/src/test/run-pass/issue-3176.rs deleted file mode 100644 index df242ee3d3059..0000000000000 --- a/src/test/run-pass/issue-3176.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// xfail-fast -// xfail-win32 #7999 - -use std::comm::{Select2, Selectable}; -use std::comm; -use std::task; - -pub fn main() { - let (p,c) = comm::stream(); - do task::try || { - let (p2,c2) = comm::stream(); - do task::spawn || { - p2.recv(); - error!("sibling fails"); - fail!(); - } - let (p3,c3) = comm::stream(); - c.send(c3); - c2.send(()); - error!("child blocks"); - let (p, c) = comm::stream(); - let mut tuple = (p, p3); - tuple.select(); - c.send(()); - }; - error!("parent tries"); - assert!(!p.recv().try_send(())); - error!("all done!"); -}