From 839311c76b5727504858f019994c6471a45eb62e Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 16 Feb 2015 12:15:30 +0200 Subject: Implement ExactSizeIterator for Args and ArgsOs Fixes #22343 --- src/libstd/sys/windows/os.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 7e684c52341..6aa1ac04ca9 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -303,6 +303,10 @@ impl Iterator for Args { fn size_hint(&self) -> (usize, Option) { self.range.size_hint() } } +impl ExactSizeIterator for Args { + fn len(&self) -> usize { self.range.len() } +} + impl Drop for Args { fn drop(&mut self) { unsafe { c::LocalFree(self.cur as *mut c_void); } -- cgit 1.4.1-3-g733a5 From 10f51fc412b36ac4456be01d549d7ecd247a517b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 17 Feb 2015 20:32:22 +0530 Subject: fix windows --- src/libstd/sys/windows/os.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 6aa1ac04ca9..502d70d4e1a 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -18,7 +18,7 @@ use os::windows::*; use error::Error as StdError; use ffi::{OsString, OsStr, AsOsStr}; use fmt; -use iter::Range; +use ops::Range; use libc::types::os::arch::extra::LPWCH; use libc::{self, c_int, c_void}; use mem; @@ -319,7 +319,7 @@ pub fn args() -> Args { let lpCmdLine = c::GetCommandLineW(); let szArgList = c::CommandLineToArgvW(lpCmdLine, &mut nArgs); - Args { cur: szArgList, range: range(0, nArgs as isize) } + Args { cur: szArgList, range: 0..(nArgs as isize) } } } -- cgit 1.4.1-3-g733a5 From d8f8f7a58c7c8b3352c1c577347865f5a823fee3 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Tue, 17 Feb 2015 01:08:53 -0800 Subject: Revise std::thread semantics This commit makes several changes to `std::thread` in preparation for final stabilization: * It removes the ability to handle panics from `scoped` children; see #20807 for discussion * It adds a `JoinHandle` structure, now returned from `spawn`, which makes it possible to join on children that do not share data from their parent's stack. The child is automatically detached when the handle is dropped, and the handle cannot be copied due to Posix semantics. * It moves all static methods from `std::thread::Thread` to free functions in `std::thread`. This was done in part because, due to the above changes, there are effectively no direct `Thread` constructors, and the static methods have tended to feel a bit awkward. * Adds an `io::Result` around the `Builder` methods `scoped` and `spawn`, making it possible to handle OS errors when creating threads. The convenience free functions entail an unwrap. * Stabilizes the entire module. Despite the fact that the API is changing somewhat here, this is part of a long period of baking and the changes are addressing all known issues prior to alpha2. If absolutely necessary, further breaking changes can be made prior to beta. Closes #20807 [breaking-change] --- src/libstd/sys/unix/thread.rs | 8 +- src/libstd/sys/windows/thread.rs | 8 +- src/libstd/thread.rs | 370 ++++++++++++++++++++++++++++----------- 3 files changed, 273 insertions(+), 113 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 6f030ee91fe..82c52471d10 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -10,6 +10,7 @@ use core::prelude::*; +use io; use boxed::Box; use cmp; use mem; @@ -191,7 +192,7 @@ pub mod guard { } } -pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread { +pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { let mut native: libc::pthread_t = mem::zeroed(); let mut attr: libc::pthread_attr_t = mem::zeroed(); assert_eq!(pthread_attr_init(&mut attr), 0); @@ -226,9 +227,10 @@ pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread { if ret != 0 { // be sure to not leak the closure let _p: Box> = mem::transmute(arg); - panic!("failed to spawn native thread: {}", ret); + Err(io::Error::from_os_error(ret)) + } else { + Ok(native) } - native } #[cfg(any(target_os = "linux", target_os = "android"))] diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index a38dc9b2d34..d7f86e1842e 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -10,6 +10,7 @@ use boxed::Box; use cmp; +use io; use mem; use ptr; use libc; @@ -42,7 +43,7 @@ pub mod guard { } } -pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread { +pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { let arg: *mut libc::c_void = mem::transmute(box p); // FIXME On UNIX, we guard against stack sizes that are too small but // that's because pthreads enforces that stacks are at least @@ -60,9 +61,10 @@ pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread { if ret as uint == 0 { // be sure to not leak the closure let _p: Box = mem::transmute(arg); - panic!("failed to spawn native thread: {:?}", ret); + Err(io::Error::last_os_error()) + } else { + Ok(ret) } - return ret; } pub unsafe fn set_name(_name: &str) { diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index cc9d7492441..4f667114d38 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -58,16 +58,16 @@ //! ```rust //! use std::thread::Thread; //! -//! let thread = Thread::spawn(move || { +//! Thread::spawn(move || { //! println!("Hello, World!"); //! // some computation here //! }); //! ``` //! -//! The spawned thread is "detached" from the current thread, meaning that it -//! can outlive the thread that spawned it. (Note, however, that when the main -//! thread terminates all detached threads are terminated as well.) The returned -//! `Thread` handle can be used for low-level synchronization as described below. +//! In this example, the spawned thread is "detached" from the current +//! thread, meaning that it can outlive the thread that spawned +//! it. (Note, however, that when the main thread terminates all +//! detached threads are terminated as well.) //! //! ## Scoped threads //! @@ -86,13 +86,13 @@ //! let result = guard.join(); //! ``` //! -//! The `scoped` function doesn't return a `Thread` directly; instead, it -//! returns a *join guard* from which a `Thread` can be extracted. The join -//! guard is an RAII-style guard that will automatically join the child thread -//! (block until it terminates) when it is dropped. You can join the child -//! thread in advance by calling the `join` method on the guard, which will also -//! return the result produced by the thread. A handle to the thread itself is -//! available via the `thread` method on the join guard. +//! The `scoped` function doesn't return a `Thread` directly; instead, +//! it returns a *join guard*. The join guard is an RAII-style guard +//! that will automatically join the child thread (block until it +//! terminates) when it is dropped. You can join the child thread in +//! advance by calling the `join` method on the guard, which will also +//! return the result produced by the thread. A handle to the thread +//! itself is available via the `thread` method on the join guard. //! //! (Note: eventually, the `scoped` constructor will allow the parent and child //! threads to data that lives on the parent thread's stack, but some language @@ -151,6 +151,8 @@ use any::Any; use boxed::Box; use cell::UnsafeCell; use clone::Clone; +use fmt; +use io; use marker::{Send, Sync}; use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; @@ -224,49 +226,58 @@ impl Builder { self } - /// Spawn a new detached thread, and return a handle to it. + /// Spawn a new thread, and return a join handle for it. /// - /// See `Thead::spawn` and the module doc for more details. - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn spawn(self, f: F) -> Thread where F: FnOnce(), F: Send + 'static { - let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(|_| {})); - unsafe { imp::detach(native) }; - thread + /// The child thread may outlive the parent (unless the parent thread + /// is the main thread; the whole process is terminated when the main + /// thread finishes.) The join handle can be used to block on + /// termination of the child thread, including recovering its panics. + /// + /// # Errors + /// + /// Unlike the `spawn` free function, this method yields an + /// `io::Result` to capture any failure to create the thread at + /// the OS level. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn spawn(self, f: F) -> io::Result where + F: FnOnce(), F: Send + 'static + { + self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i)) } /// Spawn a new child thread that must be joined within a given /// scope, and return a `JoinGuard`. /// - /// See `Thead::scoped` and the module doc for more details. - #[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] - pub fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T> where + /// The join guard can be used to explicitly join the child thread (via + /// `join`), returning `Result`, or it will implicitly join the child + /// upon being dropped. Because the child thread may refer to data on the + /// current thread's stack (hence the "scoped" name), it cannot be detached; + /// it *must* be joined before the relevant stack frame is popped. See the + /// module documentation for additional details. + /// + /// # Errors + /// + /// Unlike the `scoped` free function, this method yields an + /// `io::Result` to capture any failure to create the thread at + /// the OS level. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn scoped<'a, T, F>(self, f: F) -> io::Result> where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a { - let my_packet = Packet(Arc::new(UnsafeCell::new(None))); - let their_packet = Packet(my_packet.0.clone()); - let (native, thread) = self.spawn_inner(Thunk::new(f), Thunk::with_arg(move |ret| unsafe { - *their_packet.0.get() = Some(ret); - })); - - JoinGuard { - native: native, - joined: false, - packet: my_packet, - thread: thread, - } + self.spawn_inner(Thunk::new(f)).map(JoinGuard) } - fn spawn_inner(self, f: Thunk<(), T>, finish: Thunk, ()>) - -> (imp::rust_thread, Thread) - { + fn spawn_inner(self, f: Thunk<(), T>) -> io::Result> { let Builder { name, stack_size, stdout, stderr } = self; let stack_size = stack_size.unwrap_or(rt::min_stack()); + let my_thread = Thread::new(name); let their_thread = my_thread.clone(); + let my_packet = Packet(Arc::new(UnsafeCell::new(None))); + let their_packet = Packet(my_packet.0.clone()); + // Spawning a new OS thread guarantees that __morestack will never get // triggered, but we must manually set up the actual stack bounds once // this function starts executing. This raises the lower limit by a bit @@ -316,17 +327,120 @@ impl Builder { unwind::try(move || *ptr = Some(f.invoke(()))) } }; - finish.invoke(match (output, try_result) { - (Some(data), Ok(_)) => Ok(data), - (None, Err(cause)) => Err(cause), - _ => unreachable!() - }); + unsafe { + *their_packet.0.get() = Some(match (output, try_result) { + (Some(data), Ok(_)) => Ok(data), + (None, Err(cause)) => Err(cause), + _ => unreachable!() + }); + } }; - (unsafe { imp::create(stack_size, Thunk::new(main)) }, my_thread) + Ok(JoinInner { + native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }), + thread: my_thread, + packet: my_packet, + joined: false, + }) + } +} + +/// Spawn a new, returning a join handle for it. +/// +/// The child thread may outlive the parent (unless the parent thread +/// is the main thread; the whole process is terminated when the main +/// thread finishes.) The join handle can be used to block on +/// termination of the child thread, including recovering its panics. +/// +/// # Panics +/// +/// Panicks if the OS fails to create a thread; use `Builder::spawn` +/// to recover from such errors. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn spawn(f: F) -> JoinHandle where F: FnOnce(), F: Send + 'static { + Builder::new().spawn(f).unwrap() +} + +/// Spawn a new *scoped* thread, returning a `JoinGuard` for it. +/// +/// The join guard can be used to explicitly join the child thread (via +/// `join`), returning `Result`, or it will implicitly join the child +/// upon being dropped. Because the child thread may refer to data on the +/// current thread's stack (hence the "scoped" name), it cannot be detached; +/// it *must* be joined before the relevant stack frame is popped. See the +/// module documentation for additional details. +/// +/// # Panics +/// +/// Panicks if the OS fails to create a thread; use `Builder::scoped` +/// to recover from such errors. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where + T: Send + 'a, F: FnOnce() -> T, F: Send + 'a +{ + Builder::new().scoped(f).unwrap() +} + +/// Gets a handle to the thread that invokes it. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn current() -> Thread { + thread_info::current_thread() +} + +/// Cooperatively give up a timeslice to the OS scheduler. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn yield_now() { + unsafe { imp::yield_now() } +} + +/// Determines whether the current thread is unwinding because of panic. +#[inline] +#[stable(feature = "rust1", since = "1.0.0")] +pub fn panicking() -> bool { + unwind::panicking() +} + +/// Block unless or until the current thread's token is made available (may wake spuriously). +/// +/// See the module doc for more detail. +// +// The implementation currently uses the trivial strategy of a Mutex+Condvar +// with wakeup flag, which does not actually allow spurious wakeups. In the +// future, this will be implemented in a more efficient way, perhaps along the lines of +// http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp +// or futuxes, and in either case may allow spurious wakeups. +#[stable(feature = "rust1", since = "1.0.0")] +pub fn park() { + let thread = Thread::current(); + let mut guard = thread.inner.lock.lock().unwrap(); + while !*guard { + guard = thread.inner.cvar.wait(guard).unwrap(); } + *guard = false; } +/// Block unless or until the current thread's token is made available or +/// the specified duration has been reached (may wake spuriously). +/// +/// The semantics of this function are equivalent to `park()` except that the +/// thread will be blocked for roughly no longer than dur. This method +/// should not be used for precise timing due to anomalies such as +/// preemption or platform differences that may not cause the maximum +/// amount of time waited to be precisely dur +/// +/// See the module doc for more detail. +#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")] +pub fn park_timeout(dur: Duration) { + let thread = Thread::current(); + let mut guard = thread.inner.lock.lock().unwrap(); + if !*guard { + let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap(); + guard = g; + } + *guard = false; +} + +/// The internal representation of a `Thread` handle struct Inner { name: Option, lock: Mutex, // true when there is a buffered unpark @@ -354,62 +468,48 @@ impl Thread { } } - /// Spawn a new detached thread, returning a handle to it. - /// - /// The child thread may outlive the parent (unless the parent thread is the - /// main thread; the whole process is terminated when the main thread - /// finishes.) The thread handle can be used for low-level - /// synchronization. See the module documentation for additional details. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[unstable(feature = "std_misc", reason = "may change with specifics of new Send semantics")] pub fn spawn(f: F) -> Thread where F: FnOnce(), F: Send + 'static { - Builder::new().spawn(f) + Builder::new().spawn(f).unwrap().thread().clone() } - /// Spawn a new *scoped* thread, returning a `JoinGuard` for it. - /// - /// The join guard can be used to explicitly join the child thread (via - /// `join`), returning `Result`, or it will implicitly join the child - /// upon being dropped. Because the child thread may refer to data on the - /// current thread's stack (hence the "scoped" name), it cannot be detached; - /// it *must* be joined before the relevant stack frame is popped. See the - /// module documentation for additional details. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[unstable(feature = "std_misc", reason = "may change with specifics of new Send semantics")] pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a { - Builder::new().scoped(f) + Builder::new().scoped(f).unwrap() } - /// Gets a handle to the thread that invokes it. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[stable(feature = "rust1", since = "1.0.0")] pub fn current() -> Thread { thread_info::current_thread() } - /// Cooperatively give up a timeslice to the OS scheduler. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[unstable(feature = "std_misc", reason = "name may change")] pub fn yield_now() { unsafe { imp::yield_now() } } - /// Determines whether the current thread is unwinding because of panic. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn panicking() -> bool { unwind::panicking() } - /// Block unless or until the current thread's token is made available (may wake spuriously). - /// - /// See the module doc for more detail. - // - // The implementation currently uses the trivial strategy of a Mutex+Condvar - // with wakeup flag, which does not actually allow spurious wakeups. In the - // future, this will be implemented in a more efficient way, perhaps along the lines of - // http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp - // or futuxes, and in either case may allow spurious wakeups. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[unstable(feature = "std_misc", reason = "recently introduced")] pub fn park() { let thread = Thread::current(); @@ -420,16 +520,8 @@ impl Thread { *guard = false; } - /// Block unless or until the current thread's token is made available or - /// the specified duration has been reached (may wake spuriously). - /// - /// The semantics of this function are equivalent to `park()` except that the - /// thread will be blocked for roughly no longer than dur. This method - /// should not be used for precise timing due to anomalies such as - /// preemption or platform differences that may not cause the maximum - /// amount of time waited to be precisely dur - /// - /// See the module doc for more detail. + /// Deprecated: use module-level free fucntion. + #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")] #[unstable(feature = "std_misc", reason = "recently introduced")] pub fn park_timeout(dur: Duration) { let thread = Thread::current(); @@ -444,7 +536,7 @@ impl Thread { /// Atomically makes the handle's token available if it is not already. /// /// See the module doc for more detail. - #[unstable(feature = "std_misc", reason = "recently introduced")] + #[stable(feature = "rust1", since = "1.0.0")] pub fn unpark(&self) { let mut guard = self.inner.lock.lock().unwrap(); if !*guard { @@ -460,6 +552,13 @@ impl Thread { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Thread { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.name(), f) + } +} + // a hack to get around privacy restrictions impl thread_info::NewThread for Thread { fn new(name: Option) -> Thread { Thread::new(name) } @@ -476,19 +575,76 @@ struct Packet(Arc>>>); unsafe impl Send for Packet {} unsafe impl Sync for Packet {} -/// An RAII-style guard that will block until thread termination when dropped. -/// -/// The type `T` is the return type for the thread's main function. -#[must_use] -#[unstable(feature = "std_misc", - reason = "may change with specifics of new Send semantics")] -pub struct JoinGuard<'a, T: 'a> { +/// Inner representation for JoinHandle and JoinGuard +struct JoinInner { native: imp::rust_thread, thread: Thread, - joined: bool, packet: Packet, + joined: bool, } +impl JoinInner { + fn join(&mut self) -> Result { + assert!(!self.joined); + unsafe { imp::join(self.native) }; + self.joined = true; + unsafe { + (*self.packet.0.get()).take().unwrap() + } + } +} + +/// An owned permission to join on a thread (block on its termination). +/// +/// Unlike a `JoinGuard`, a `JoinHandle` *detaches* the child thread +/// when it is dropped, rather than automatically joining on drop. +/// +/// Due to platform restrictions, it is not possible to `Clone` this +/// handle: the ability to join a child thread is a uniquely-owned +/// permission. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct JoinHandle(JoinInner<()>); + +impl JoinHandle { + /// Extract a handle to the underlying thread + #[stable(feature = "rust1", since = "1.0.0")] + pub fn thread(&self) -> &Thread { + &self.0.thread + } + + /// Wait for the associated thread to finish. + /// + /// If the child thread panics, `Err` is returned with the parameter given + /// to `panic`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn join(mut self) -> Result<()> { + self.0.join() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Drop for JoinHandle { + fn drop(&mut self) { + if !self.0.joined { + unsafe { imp::detach(self.0.native) } + } + } +} + +/// An RAII-style guard that will block until thread termination when dropped. +/// +/// The type `T` is the return type for the thread's main function. +/// +/// Joining on drop is necessary to ensure memory safety when stack +/// data is shared between a parent and child thread. +/// +/// Due to platform restrictions, it is not possible to `Clone` this +/// handle: the ability to join a child thread is a uniquely-owned +/// permission. +#[must_use] +#[stable(feature = "rust1", since = "1.0.0")] +pub struct JoinGuard<'a, T: 'a>(JoinInner); + #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {} @@ -496,32 +652,32 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { /// Extract a handle to the thread this guard will join on. #[stable(feature = "rust1", since = "1.0.0")] pub fn thread(&self) -> &Thread { - &self.thread + &self.0.thread } /// Wait for the associated thread to finish, returning the result of the thread's /// calculation. /// - /// If the child thread panics, `Err` is returned with the parameter given - /// to `panic`. + /// # Panics + /// + /// Panics on the child thread are propagated by panicking the parent. #[stable(feature = "rust1", since = "1.0.0")] - pub fn join(mut self) -> Result { - assert!(!self.joined); - unsafe { imp::join(self.native) }; - self.joined = true; - unsafe { - (*self.packet.0.get()).take().unwrap() + pub fn join(mut self) -> T { + match self.0.join() { + Ok(res) => res, + Err(_) => panic!("child thread {:?} panicked", self.thread()), } } } +#[stable(feature = "rust1", since = "1.0.0")] impl JoinGuard<'static, T> { /// Detaches the child thread, allowing it to outlive its parent. - #[unstable(feature = "std_misc", - reason = "unsure whether this API imposes limitations elsewhere")] + #[deprecated(since = "1.0.0", reason = "use spawn instead")] + #[unstable(feature = "std_misc")] pub fn detach(mut self) { - unsafe { imp::detach(self.native) }; - self.joined = true; // avoid joining in the destructor + unsafe { imp::detach(self.0.native) }; + self.0.joined = true; // avoid joining in the destructor } } @@ -529,8 +685,8 @@ impl JoinGuard<'static, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { fn drop(&mut self) { - if !self.joined { - unsafe { imp::join(self.native) }; + if !self.0.joined { + unsafe { imp::join(self.0.native) }; } } } -- cgit 1.4.1-3-g733a5 From 6ac3799b75780f8c18bc38331403e1e517b89bab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Feb 2015 15:24:34 -0800 Subject: Test fixes and rebase conflicts --- src/doc/trpl/concurrency.md | 62 ++++++++-------------- src/libcore/cmp.rs | 9 ++-- src/libgetopts/lib.rs | 1 + src/librustc_driver/lib.rs | 5 +- src/librustc_trans/back/write.rs | 2 +- src/librustdoc/lib.rs | 12 +++-- src/libstd/sys/windows/thread.rs | 3 +- src/libstd/thread.rs | 36 ++++++------- src/libterm/lib.rs | 1 + src/libtest/lib.rs | 4 +- src/test/compile-fail/issue-8460-const.rs | 40 +++++++------- src/test/compile-fail/lint-uppercase-variables.rs | 4 +- src/test/run-fail/panic-task-name-none.rs | 3 +- src/test/run-fail/panic-task-name-owned.rs | 8 +-- .../cleanup-rvalue-temp-during-incomplete-alloc.rs | 4 +- src/test/run-pass/issue-12684.rs | 4 +- src/test/run-pass/issue-16560.rs | 4 +- src/test/run-pass/issue-16671.rs | 4 +- src/test/run-pass/issue-4446.rs | 4 +- src/test/run-pass/issue-4448.rs | 4 +- src/test/run-pass/issue-8460.rs | 42 +++++++-------- src/test/run-pass/logging-only-prints-once.rs | 4 +- src/test/run-pass/no-landing-pads.rs | 4 +- src/test/run-pass/panic-in-dtor-drops-fields.rs | 4 +- src/test/run-pass/sendfn-spawn-with-fn-arg.rs | 4 +- src/test/run-pass/sepcomp-unwind.rs | 4 +- src/test/run-pass/slice-panic-1.rs | 4 +- src/test/run-pass/slice-panic-2.rs | 4 +- src/test/run-pass/spawn-types.rs | 4 +- src/test/run-pass/spawn.rs | 4 +- src/test/run-pass/spawn2.rs | 4 +- src/test/run-pass/task-stderr.rs | 5 +- src/test/run-pass/tempfile.rs | 16 +++--- src/test/run-pass/terminate-in-initializer.rs | 6 +-- 34 files changed, 155 insertions(+), 168 deletions(-) (limited to 'src/libstd/sys/windows') diff --git a/src/doc/trpl/concurrency.md b/src/doc/trpl/concurrency.md index 3c933c1c5af..9f8f76e1fea 100644 --- a/src/doc/trpl/concurrency.md +++ b/src/doc/trpl/concurrency.md @@ -57,13 +57,13 @@ place! ## Threads Rust's standard library provides a library for 'threads', which allow you to -run Rust code in parallel. Here's a basic example of using `Thread`: +run Rust code in parallel. Here's a basic example of using `std::thread`: ``` -use std::thread::Thread; +use std::thread; fn main() { - Thread::scoped(|| { + thread::scoped(|| { println!("Hello from a thread!"); }); } @@ -73,10 +73,10 @@ The `Thread::scoped()` method accepts a closure, which is executed in a new thread. It's called `scoped` because this thread returns a join guard: ``` -use std::thread::Thread; +use std::thread; fn main() { - let guard = Thread::scoped(|| { + let guard = thread::scoped(|| { println!("Hello from a thread!"); }); @@ -85,15 +85,15 @@ fn main() { ``` When `guard` goes out of scope, it will block execution until the thread is -finished. If we didn't want this behaviour, we could use `Thread::spawn()`: +finished. If we didn't want this behaviour, we could use `thread::spawn()`: ``` -use std::thread::Thread; +use std::thread; use std::old_io::timer; use std::time::Duration; fn main() { - Thread::spawn(|| { + thread::spawn(|| { println!("Hello from a thread!"); }); @@ -101,24 +101,6 @@ fn main() { } ``` -Or call `.detach()`: - -``` -use std::thread::Thread; -use std::old_io::timer; -use std::time::Duration; - -fn main() { - let guard = Thread::scoped(|| { - println!("Hello from a thread!"); - }); - - guard.detach(); - - timer::sleep(Duration::milliseconds(50)); -} -``` - We need to `sleep` here because when `main()` ends, it kills all of the running threads. @@ -164,7 +146,7 @@ As an example, here is a Rust program that would have a data race in many languages. It will not compile: ```ignore -use std::thread::Thread; +use std::thread; use std::old_io::timer; use std::time::Duration; @@ -172,7 +154,7 @@ fn main() { let mut data = vec![1u32, 2, 3]; for i in 0..2 { - Thread::spawn(move || { + thread::spawn(move || { data[i] += 1; }); } @@ -203,7 +185,7 @@ only one person at a time can mutate what's inside. For that, we can use the but for a different reason: ```ignore -use std::thread::Thread; +use std::thread; use std::old_io::timer; use std::time::Duration; use std::sync::Mutex; @@ -213,7 +195,7 @@ fn main() { for i in 0..2 { let data = data.lock().unwrap(); - Thread::spawn(move || { + thread::spawn(move || { data[i] += 1; }); } @@ -255,7 +237,7 @@ We can use `Arc` to fix this. Here's the working version: ``` use std::sync::{Arc, Mutex}; -use std::thread::Thread; +use std::thread; use std::old_io::timer; use std::time::Duration; @@ -264,7 +246,7 @@ fn main() { for i in 0us..2 { let data = data.clone(); - Thread::spawn(move || { + thread::spawn(move || { let mut data = data.lock().unwrap(); data[i] += 1; }); @@ -280,14 +262,14 @@ thread more closely: ``` # use std::sync::{Arc, Mutex}; -# use std::thread::Thread; +# use std::thread; # use std::old_io::timer; # use std::time::Duration; # fn main() { # let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); # for i in 0us..2 { # let data = data.clone(); -Thread::spawn(move || { +thread::spawn(move || { let mut data = data.lock().unwrap(); data[i] += 1; }); @@ -315,7 +297,7 @@ than waiting for a specific time: ``` use std::sync::{Arc, Mutex}; -use std::thread::Thread; +use std::thread; use std::sync::mpsc; fn main() { @@ -326,7 +308,7 @@ fn main() { for _ in 0..10 { let (data, tx) = (data.clone(), tx.clone()); - Thread::spawn(move || { + thread::spawn(move || { let mut data = data.lock().unwrap(); *data += 1; @@ -348,7 +330,7 @@ is `Send` over the channel! ``` use std::sync::{Arc, Mutex}; -use std::thread::Thread; +use std::thread; use std::sync::mpsc; fn main() { @@ -357,7 +339,7 @@ fn main() { for _ in 0..10 { let tx = tx.clone(); - Thread::spawn(move || { + thread::spawn(move || { let answer = 42u32; tx.send(answer); @@ -378,9 +360,9 @@ A `panic!` will crash the currently executing thread. You can use Rust's threads as a simple isolation mechanism: ``` -use std::thread::Thread; +use std::thread; -let result = Thread::scoped(move || { +let result = thread::spawn(move || { panic!("oops!"); }).join(); diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 5bc634936cf..19ec245300d 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -87,8 +87,8 @@ pub trait PartialEq { /// - symmetric: `a == b` implies `b == a`; and /// - transitive: `a == b` and `b == c` implies `a == c`. /// -/// This property cannot be checked by the compiler, and therefore `Eq` implies `PartialEq`, and -/// has no extra methods. +/// This property cannot be checked by the compiler, and therefore `Eq` implies +/// `PartialEq`, and has no extra methods. #[stable(feature = "rust1", since = "1.0.0")] pub trait Eq: PartialEq { // FIXME #13101: this method is used solely by #[deriving] to @@ -100,6 +100,7 @@ pub trait Eq: PartialEq { // This should never be implemented by hand. #[doc(hidden)] #[inline(always)] + #[stable(feature = "rust1", since = "1.0.0")] fn assert_receiver_is_total_eq(&self) {} } @@ -408,7 +409,7 @@ pub fn max(v1: T, v2: T) -> T { /// ``` /// use std::cmp; /// -/// let result = cmp::partial_min(std::f64::NAN, &1.0); +/// let result = cmp::partial_min(std::f64::NAN, 1.0); /// assert_eq!(result, None); /// ``` #[inline] @@ -439,7 +440,7 @@ pub fn partial_min(v1: T, v2: T) -> Option { /// ``` /// use std::cmp; /// -/// let result = cmp::partial_max(std::f64::NAN, &1.0); +/// let result = cmp::partial_max(std::f64::NAN, 1.0); /// assert_eq!(result, None); /// ``` #[inline] diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index ca184fb8736..c743119f409 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -92,6 +92,7 @@ #![feature(collections)] #![feature(int_uint)] #![feature(staged_api)] +#![feature(str_words)] #![cfg_attr(test, feature(rustc_private))] #[cfg(test)] #[macro_use] extern crate log; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 19a290282d6..234809e5284 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -37,7 +37,6 @@ #![feature(rustc_private)] #![feature(unsafe_destructor)] #![feature(staged_api)] -#![feature(std_misc)] #![feature(unicode)] extern crate arena; @@ -73,7 +72,7 @@ use rustc::metadata; use rustc::util::common::time; use std::cmp::Ordering::Equal; -use std::old_io; +use std::old_io::{self, stdio}; use std::iter::repeat; use std::env; use std::sync::mpsc::channel; @@ -780,7 +779,7 @@ pub fn monitor(f: F) { cfg = cfg.stack_size(STACK_SIZE); } - match cfg.scoped(move || { std::old_io::stdio::set_stderr(box w); f() }).join() { + match cfg.spawn(move || { stdio::set_stderr(box w); f() }).unwrap().join() { Ok(()) => { /* fallthrough */ } Err(value) => { // Thread panicked without emitting a fatal diagnostic diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 68f413eff85..9934d9993d6 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -939,7 +939,7 @@ fn run_work_multithreaded(sess: &Session, } tx.take().unwrap().send(()).unwrap(); - }); + }).unwrap(); } let mut panicked = false; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index e2799eec90a..bab734db126 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -34,6 +34,7 @@ #![feature(std_misc)] #![feature(test)] #![feature(unicode)] +#![feature(str_words)] extern crate arena; extern crate getopts; @@ -55,6 +56,7 @@ use std::env; use std::old_io::File; use std::old_io; use std::rc::Rc; +use std::sync::mpsc::channel; use externalfiles::ExternalHtml; use serialize::Decodable; use serialize::json::{self, Json}; @@ -125,8 +127,8 @@ pub fn main() { let res = std::thread::Builder::new().stack_size(STACK_SIZE).scoped(move || { let s = env::args().collect::>(); main_args(&s) - }).join(); - env::set_exit_status(res.ok().unwrap() as i32); + }).unwrap().join(); + env::set_exit_status(res as i32); } pub fn opts() -> Vec { @@ -365,12 +367,14 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche let cr = Path::new(cratefile); info!("starting to run rustc"); - let (mut krate, analysis) = std::thread::spawn(move || { + let (tx, rx) = channel(); + std::thread::spawn(move || { use rustc::session::config::Input; let cr = cr; - core::run_core(paths, cfgs, externs, Input::File(cr), triple) + tx.send(core::run_core(paths, cfgs, externs, Input::File(cr), triple)).unwrap(); }).join().map_err(|_| "rustc failed").unwrap(); + let (mut krate, analysis) = rx.recv().unwrap(); info!("finished with rustc"); let mut analysis = Some(analysis); ANALYSISKEY.with(|s| { diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index d7f86e1842e..f3a27877e5c 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -8,7 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use boxed::Box; +use prelude::v1::*; + use cmp; use io; use mem; diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index d0fde8344b2..a8355c34000 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -147,21 +147,16 @@ #![stable(feature = "rust1", since = "1.0.0")] +use prelude::v1::*; + use any::Any; -use boxed::Box; use cell::UnsafeCell; -use clone::Clone; use fmt; use io; -use marker::{Send, Sync}; -use ops::{Drop, FnOnce}; -use option::Option::{self, Some, None}; -use result::Result::{Err, Ok}; -use sync::{Mutex, Condvar, Arc}; -use str::Str; -use string::String; +use marker; +use old_io::stdio; use rt::{self, unwind}; -use old_io::{Writer, stdio}; +use sync::{Mutex, Condvar, Arc}; use thunk::Thunk; use time::Duration; @@ -264,7 +259,9 @@ impl Builder { pub fn scoped<'a, T, F>(self, f: F) -> io::Result> where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a { - self.spawn_inner(Thunk::new(f)).map(JoinGuard) + self.spawn_inner(Thunk::new(f)).map(|inner| { + JoinGuard { inner: inner, _marker: marker::PhantomData } + }) } fn spawn_inner(self, f: Thunk<(), T>) -> io::Result> { @@ -643,7 +640,10 @@ impl Drop for JoinHandle { /// permission. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -pub struct JoinGuard<'a, T: 'a>(JoinInner); +pub struct JoinGuard<'a, T: 'a> { + inner: JoinInner, + _marker: marker::PhantomData<&'a T>, +} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {} @@ -652,7 +652,7 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { /// Extract a handle to the thread this guard will join on. #[stable(feature = "rust1", since = "1.0.0")] pub fn thread(&self) -> &Thread { - &self.0.thread + &self.inner.thread } /// Wait for the associated thread to finish, returning the result of the thread's @@ -663,7 +663,7 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> { /// Panics on the child thread are propagated by panicking the parent. #[stable(feature = "rust1", since = "1.0.0")] pub fn join(mut self) -> T { - match self.0.join() { + match self.inner.join() { Ok(res) => res, Err(_) => panic!("child thread {:?} panicked", self.thread()), } @@ -676,8 +676,8 @@ impl JoinGuard<'static, T> { #[deprecated(since = "1.0.0", reason = "use spawn instead")] #[unstable(feature = "std_misc")] pub fn detach(mut self) { - unsafe { imp::detach(self.0.native) }; - self.0.joined = true; // avoid joining in the destructor + unsafe { imp::detach(self.inner.native) }; + self.inner.joined = true; // avoid joining in the destructor } } @@ -685,8 +685,8 @@ impl JoinGuard<'static, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> { fn drop(&mut self) { - if !self.0.joined { - unsafe { imp::join(self.0.native) }; + if !self.inner.joined { + unsafe { imp::join(self.inner.native) }; } } } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 6cd96769ed2..304f370a199 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -59,6 +59,7 @@ #![feature(rustc_private)] #![feature(staged_api)] #![feature(unicode)] +#![feature(std_misc)] #![feature(env)] #![cfg_attr(windows, feature(libc))] diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 32ba410224e..62bf95d3b7b 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -75,7 +75,7 @@ use std::iter::repeat; use std::num::{Float, Int}; use std::env; use std::sync::mpsc::{channel, Sender}; -use std::thread::{self, Thread}; +use std::thread; use std::thunk::{Thunk, Invoke}; use std::time::Duration; @@ -895,7 +895,7 @@ pub fn run_test(opts: &TestOpts, cfg = cfg.stderr(box stderr as Box); } - let result_guard = cfg.scoped(move || { testfn.invoke(()) }); + let result_guard = cfg.spawn(move || { testfn.invoke(()) }).unwrap(); let stdout = reader.read_to_end().unwrap().into_iter().collect(); let test_result = calc_result(&desc, result_guard.join()); monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); diff --git a/src/test/compile-fail/issue-8460-const.rs b/src/test/compile-fail/issue-8460-const.rs index 4e44b4dcdce..b6d371e4b11 100644 --- a/src/test/compile-fail/issue-8460-const.rs +++ b/src/test/compile-fail/issue-8460-const.rs @@ -12,44 +12,44 @@ use std::{int, i8, i16, i32, i64}; use std::thread; fn main() { - assert!(thread::spawn(move|| int::MIN / -1).join().is_err()); + assert!(thread::spawn(move|| { int::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression - assert!(thread::spawn(move|| i8::MIN / -1).join().is_err()); + assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression - assert!(thread::spawn(move|| i16::MIN / -1).join().is_err()); + assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression - assert!(thread::spawn(move|| i32::MIN / -1).join().is_err()); + assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression - assert!(thread::spawn(move|| i64::MIN / -1).join().is_err()); + assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); //~^ ERROR attempted to divide with overflow in a constant expression - assert!(thread::spawn(move|| 1is / 0).join().is_err()); + assert!(thread::spawn(move|| { 1is / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| 1i8 / 0).join().is_err()); + assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| 1i16 / 0).join().is_err()); + assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| 1i32 / 0).join().is_err()); + assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| 1i64 / 0).join().is_err()); + assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); //~^ ERROR attempted to divide by zero in a constant expression - assert!(thread::spawn(move|| int::MIN % -1).join().is_err()); + assert!(thread::spawn(move|| { int::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression - assert!(thread::spawn(move|| i8::MIN % -1).join().is_err()); + assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression - assert!(thread::spawn(move|| i16::MIN % -1).join().is_err()); + assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression - assert!(thread::spawn(move|| i32::MIN % -1).join().is_err()); + assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression - assert!(thread::spawn(move|| i64::MIN % -1).join().is_err()); + assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); //~^ ERROR attempted remainder with overflow in a constant expression - assert!(thread::spawn(move|| 1is % 0).join().is_err()); + assert!(thread::spawn(move|| { 1is % 0; }).join().is_err()); //~^ ERROR attempted remainder with a divisor of zero in a constant expression - assert!(thread::spawn(move|| 1i8 % 0).join().is_err()); + assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); //~^ ERROR attempted remainder with a divisor of zero in a constant expression - assert!(thread::spawn(move|| 1i16 % 0).join().is_err()); + assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); //~^ ERROR attempted remainder with a divisor of zero in a constant expression - assert!(thread::spawn(move|| 1i32 % 0).join().is_err()); + assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); //~^ ERROR attempted remainder with a divisor of zero in a constant expression - assert!(thread::spawn(move|| 1i64 % 0).join().is_err()); + assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); //~^ ERROR attempted remainder with a divisor of zero in a constant expression } diff --git a/src/test/compile-fail/lint-uppercase-variables.rs b/src/test/compile-fail/lint-uppercase-variables.rs index b68d9dc4645..a4f46cbd187 100644 --- a/src/test/compile-fail/lint-uppercase-variables.rs +++ b/src/test/compile-fail/lint-uppercase-variables.rs @@ -13,9 +13,6 @@ #![allow(dead_code)] #![deny(non_snake_case)] -use std::old_io::File; -use std::old_io::IoError; - mod foo { pub enum Foo { Foo } } @@ -36,6 +33,7 @@ fn main() { Foo => {} //~^ ERROR variable `Foo` should have a snake case name such as `foo` //~^^ WARN `Foo` is named the same as one of the variants of the type `foo::Foo` +//~^^^ WARN unused variable: `Foo` } test(1); diff --git a/src/test/run-fail/panic-task-name-none.rs b/src/test/run-fail/panic-task-name-none.rs index 40a881852f5..3a5ac5a1009 100644 --- a/src/test/run-fail/panic-task-name-none.rs +++ b/src/test/run-fail/panic-task-name-none.rs @@ -13,9 +13,8 @@ use std::thread; fn main() { - let r: Result = thread::spawn(move|| { + let r: Result<(),_> = thread::spawn(move|| { panic!("test"); - 1 }).join(); assert!(r.is_ok()); } diff --git a/src/test/run-fail/panic-task-name-owned.rs b/src/test/run-fail/panic-task-name-owned.rs index d48d282c9eb..8cab9e05f96 100644 --- a/src/test/run-fail/panic-task-name-owned.rs +++ b/src/test/run-fail/panic-task-name-owned.rs @@ -13,9 +13,9 @@ use std::thread::Builder; fn main() { - let r: Result = Builder::new().name("owned name".to_string()).scoped(move|| { + let r: () = Builder::new().name("owned name".to_string()).scoped(move|| { panic!("test"); - 1 - }).join(); - assert!(r.is_ok()); + () + }).unwrap().join(); + panic!(); } diff --git a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs index edb3d72483b..96ae7e3d336 100644 --- a/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs +++ b/src/test/run-pass/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -27,7 +27,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -use std::thread::Thread; +use std::thread; enum Conzabble { Bickwick(Foo) @@ -48,5 +48,5 @@ pub fn fails() { } pub fn main() { - Thread::scoped(fails).join(); + thread::spawn(fails).join(); } diff --git a/src/test/run-pass/issue-12684.rs b/src/test/run-pass/issue-12684.rs index 38731b8c8da..e66b5d21e17 100644 --- a/src/test/run-pass/issue-12684.rs +++ b/src/test/run-pass/issue-12684.rs @@ -9,10 +9,10 @@ // except according to those terms. use std::time::Duration; -use std::thread::Thread; +use std::thread; fn main() { - Thread::scoped(move|| customtask()).join().ok().unwrap(); + thread::spawn(move|| customtask()).join().ok().unwrap(); } fn customtask() { diff --git a/src/test/run-pass/issue-16560.rs b/src/test/run-pass/issue-16560.rs index ca40b2fe4c7..9448e605937 100644 --- a/src/test/run-pass/issue-16560.rs +++ b/src/test/run-pass/issue-16560.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -use std::thread::Thread; +use std::thread; use std::mem; fn main() { @@ -20,7 +20,7 @@ fn main() { // Check that both closures are capturing by value assert_eq!(1, mem::size_of_val(&closure)); - Thread::scoped(move|| { + thread::spawn(move|| { let ok = closure; }).join().ok().unwrap(); } diff --git a/src/test/run-pass/issue-16671.rs b/src/test/run-pass/issue-16671.rs index 124b0205fae..0e42f2593f2 100644 --- a/src/test/run-pass/issue-16671.rs +++ b/src/test/run-pass/issue-16671.rs @@ -18,11 +18,11 @@ // A var moved into a proc, that has a mutable loan path should // not trigger a misleading unused_mut warning. -use std::thread::Thread; +use std::thread; pub fn main() { let mut stdin = std::old_io::stdin(); - Thread::spawn(move|| { + thread::spawn(move|| { let _ = stdin.read_to_end(); }); } diff --git a/src/test/run-pass/issue-4446.rs b/src/test/run-pass/issue-4446.rs index ec4cd02e9fd..b40a726a2c3 100644 --- a/src/test/run-pass/issue-4446.rs +++ b/src/test/run-pass/issue-4446.rs @@ -10,14 +10,14 @@ use std::old_io::println; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; pub fn main() { let (tx, rx) = channel(); tx.send("hello, world").unwrap(); - Thread::scoped(move|| { + thread::spawn(move|| { println(rx.recv().unwrap()); }).join().ok().unwrap(); } diff --git a/src/test/run-pass/issue-4448.rs b/src/test/run-pass/issue-4448.rs index a19bfca721a..ef30f9182ba 100644 --- a/src/test/run-pass/issue-4448.rs +++ b/src/test/run-pass/issue-4448.rs @@ -9,12 +9,12 @@ // except according to those terms. use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; pub fn main() { let (tx, rx) = channel::<&'static str>(); - let t = Thread::scoped(move|| { + let t = thread::spawn(move|| { assert_eq!(rx.recv().unwrap(), "hello, world"); }); diff --git a/src/test/run-pass/issue-8460.rs b/src/test/run-pass/issue-8460.rs index 4b9ed44c7cd..72a1ec436f3 100644 --- a/src/test/run-pass/issue-8460.rs +++ b/src/test/run-pass/issue-8460.rs @@ -9,31 +9,31 @@ // except according to those terms. use std::num::Int; -use std::thread::Thread; +use std::thread; // Avoid using constants, which would trigger compile-time errors. fn min_val() -> T { Int::min_value() } fn zero() -> T { Int::zero() } fn main() { - assert!(Thread::scoped(move|| min_val::() / -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() / -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() / -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() / -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() / -1).join().is_err()); - assert!(Thread::scoped(move|| 1is / zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i8 / zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i16 / zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i32 / zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i64 / zero()).join().is_err()); - assert!(Thread::scoped(move|| min_val::() % -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() % -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() % -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() % -1).join().is_err()); - assert!(Thread::scoped(move|| min_val::() % -1).join().is_err()); - assert!(Thread::scoped(move|| 1is % zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i8 % zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i16 % zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i32 % zero()).join().is_err()); - assert!(Thread::scoped(move|| 1i64 % zero()).join().is_err()); + assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() / -1; }).join().is_err()); + assert!(thread::spawn(move|| { 1is / zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i8 / zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i16 / zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i32 / zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i64 / zero(); }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { min_val::() % -1; }).join().is_err()); + assert!(thread::spawn(move|| { 1is % zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i8 % zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i16 % zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i32 % zero(); }).join().is_err()); + assert!(thread::spawn(move|| { 1i64 % zero(); }).join().is_err()); } diff --git a/src/test/run-pass/logging-only-prints-once.rs b/src/test/run-pass/logging-only-prints-once.rs index 644efe20ded..b03c4b5ff47 100644 --- a/src/test/run-pass/logging-only-prints-once.rs +++ b/src/test/run-pass/logging-only-prints-once.rs @@ -13,7 +13,7 @@ use std::cell::Cell; use std::fmt; -use std::thread::Thread; +use std::thread; struct Foo(Cell); @@ -27,7 +27,7 @@ impl fmt::Debug for Foo { } pub fn main() { - Thread::scoped(move|| { + thread::spawn(move|| { let mut f = Foo(Cell::new(0)); println!("{:?}", f); let Foo(ref mut f) = f; diff --git a/src/test/run-pass/no-landing-pads.rs b/src/test/run-pass/no-landing-pads.rs index c90c6ce87f0..5ce32e4fe2c 100644 --- a/src/test/run-pass/no-landing-pads.rs +++ b/src/test/run-pass/no-landing-pads.rs @@ -10,7 +10,7 @@ // compile-flags: -Z no-landing-pads -use std::thread::Thread; +use std::thread; static mut HIT: bool = false; @@ -23,7 +23,7 @@ impl Drop for A { } fn main() { - Thread::scoped(move|| -> () { + thread::spawn(move|| -> () { let _a = A; panic!(); }).join().err().unwrap(); diff --git a/src/test/run-pass/panic-in-dtor-drops-fields.rs b/src/test/run-pass/panic-in-dtor-drops-fields.rs index 3cc01b967ce..6da15b97aca 100644 --- a/src/test/run-pass/panic-in-dtor-drops-fields.rs +++ b/src/test/run-pass/panic-in-dtor-drops-fields.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +use std::thread; static mut dropped: bool = false; @@ -33,7 +33,7 @@ impl Drop for B { } pub fn main() { - let ret = Thread::scoped(move|| { + let ret = thread::spawn(move|| { let _a = A { b: B { foo: 3 } }; }).join(); assert!(ret.is_err()); diff --git a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs index 6c9707103b9..523b7528103 100644 --- a/src/test/run-pass/sendfn-spawn-with-fn-arg.rs +++ b/src/test/run-pass/sendfn-spawn-with-fn-arg.rs @@ -11,7 +11,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -use std::thread::Thread; +use std::thread; pub fn main() { test05(); } @@ -25,7 +25,7 @@ fn test05() { println!("{}", *three + n); // will copy x into the closure assert_eq!(*three, 3); }; - Thread::scoped(move|| { + thread::spawn(move|| { test05_start(fn_to_send); }).join().ok().unwrap(); } diff --git a/src/test/run-pass/sepcomp-unwind.rs b/src/test/run-pass/sepcomp-unwind.rs index f68dea04a08..21c5a6fc83a 100644 --- a/src/test/run-pass/sepcomp-unwind.rs +++ b/src/test/run-pass/sepcomp-unwind.rs @@ -19,7 +19,7 @@ // In any case, this test should let us know if enabling parallel codegen ever // breaks unwinding. -use std::thread::Thread; +use std::thread; fn pad() -> uint { 0 } @@ -36,5 +36,5 @@ mod b { } fn main() { - Thread::scoped(move|| { ::b::g() }).join().err().unwrap(); + thread::spawn(move|| { ::b::g() }).join().err().unwrap(); } diff --git a/src/test/run-pass/slice-panic-1.rs b/src/test/run-pass/slice-panic-1.rs index b2e3d83ca9b..639ffd56002 100644 --- a/src/test/run-pass/slice-panic-1.rs +++ b/src/test/run-pass/slice-panic-1.rs @@ -10,7 +10,7 @@ // Test that if a slicing expr[..] fails, the correct cleanups happen. -use std::thread::Thread; +use std::thread; struct Foo; @@ -26,6 +26,6 @@ fn foo() { } fn main() { - let _ = Thread::scoped(move|| foo()).join(); + let _ = thread::spawn(move|| foo()).join(); unsafe { assert!(DTOR_COUNT == 2); } } diff --git a/src/test/run-pass/slice-panic-2.rs b/src/test/run-pass/slice-panic-2.rs index dea45e63ab0..4a2038175d2 100644 --- a/src/test/run-pass/slice-panic-2.rs +++ b/src/test/run-pass/slice-panic-2.rs @@ -10,7 +10,7 @@ // Test that if a slicing expr[..] fails, the correct cleanups happen. -use std::thread::Thread; +use std::thread; struct Foo; @@ -30,6 +30,6 @@ fn foo() { } fn main() { - let _ = Thread::scoped(move|| foo()).join(); + let _ = thread::spawn(move|| foo()).join(); unsafe { assert!(DTOR_COUNT == 2); } } diff --git a/src/test/run-pass/spawn-types.rs b/src/test/run-pass/spawn-types.rs index eaad2abe8f7..bf2f03b3e6d 100644 --- a/src/test/run-pass/spawn-types.rs +++ b/src/test/run-pass/spawn-types.rs @@ -14,7 +14,7 @@ Arnold. */ -use std::thread::Thread; +use std::thread; use std::sync::mpsc::{channel, Sender}; type ctx = Sender; @@ -25,6 +25,6 @@ fn iotask(_tx: &ctx, ip: String) { pub fn main() { let (tx, _rx) = channel::(); - let t = Thread::scoped(move|| iotask(&tx, "localhost".to_string()) ); + let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); t.join().ok().unwrap(); } diff --git a/src/test/run-pass/spawn.rs b/src/test/run-pass/spawn.rs index 8f937afa6b9..90b47f4986b 100644 --- a/src/test/run-pass/spawn.rs +++ b/src/test/run-pass/spawn.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +use std::thread; pub fn main() { - Thread::scoped(move|| child(10)).join().ok().unwrap(); + thread::spawn(move|| child(10)).join().ok().unwrap(); } fn child(i: int) { println!("{}", i); assert!((i == 10)); } diff --git a/src/test/run-pass/spawn2.rs b/src/test/run-pass/spawn2.rs index 75104a4ddef..91edb5fd9c1 100644 --- a/src/test/run-pass/spawn2.rs +++ b/src/test/run-pass/spawn2.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::thread::Thread; +use std::thread; pub fn main() { - let t = Thread::scoped(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); + let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); t.join().ok().unwrap(); } diff --git a/src/test/run-pass/task-stderr.rs b/src/test/run-pass/task-stderr.rs index 5994b24dfdc..1c263b19dd1 100644 --- a/src/test/run-pass/task-stderr.rs +++ b/src/test/run-pass/task-stderr.rs @@ -20,9 +20,10 @@ fn main() { let mut reader = ChanReader::new(rx); let stderr = ChanWriter::new(tx); - let res = thread::Builder::new().stderr(box stderr as Box).scoped(move|| -> () { + let res = thread::Builder::new().stderr(box stderr as Box) + .spawn(move|| -> () { panic!("Hello, world!") - }).join(); + }).unwrap().join(); assert!(res.is_err()); let output = reader.read_to_string().unwrap(); diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs index 4df1ff14810..053df3a57f3 100644 --- a/src/test/run-pass/tempfile.rs +++ b/src/test/run-pass/tempfile.rs @@ -23,7 +23,7 @@ use std::old_io::{fs, TempDir}; use std::old_io; use std::os; use std::sync::mpsc::channel; -use std::thread::Thread; +use std::thread; fn test_tempdir() { let path = { @@ -42,7 +42,7 @@ fn test_rm_tempdir() { tx.send(tmp.path().clone()).unwrap(); panic!("panic to unwind past `tmp`"); }; - let _ = Thread::scoped(f).join(); + thread::spawn(f).join(); let path = rx.recv().unwrap(); assert!(!path.exists()); @@ -52,7 +52,7 @@ fn test_rm_tempdir() { let _tmp = tmp; panic!("panic to unwind past `tmp`"); }; - let _ = Thread::scoped(f).join(); + thread::spawn(f).join(); assert!(!path.exists()); let path; @@ -61,7 +61,7 @@ fn test_rm_tempdir() { TempDir::new("test_rm_tempdir").unwrap() }; // FIXME(#16640) `: TempDir` annotation shouldn't be necessary - let tmp: TempDir = Thread::scoped(f).join().ok().expect("test_rm_tmdir"); + let tmp: TempDir = thread::scoped(f).join(); path = tmp.path().clone(); assert!(path.exists()); } @@ -85,7 +85,7 @@ fn test_rm_tempdir_close() { tmp.close(); panic!("panic when unwinding past `tmp`"); }; - let _ = Thread::scoped(f).join(); + thread::spawn(f).join(); let path = rx.recv().unwrap(); assert!(!path.exists()); @@ -96,7 +96,7 @@ fn test_rm_tempdir_close() { tmp.close(); panic!("panic when unwinding past `tmp`"); }; - let _ = Thread::scoped(f).join(); + thread::spawn(f).join(); assert!(!path.exists()); let path; @@ -105,7 +105,7 @@ fn test_rm_tempdir_close() { TempDir::new("test_rm_tempdir").unwrap() }; // FIXME(#16640) `: TempDir` annotation shouldn't be necessary - let tmp: TempDir = Thread::scoped(f).join().ok().expect("test_rm_tmdir"); + let tmp: TempDir = thread::scoped(f).join(); path = tmp.path().clone(); assert!(path.exists()); tmp.close(); @@ -179,7 +179,7 @@ pub fn test_rmdir_recursive_ok() { } pub fn dont_double_panic() { - let r: Result<(), _> = Thread::scoped(move|| { + let r: Result<(), _> = thread::spawn(move|| { let tmpdir = TempDir::new("test").unwrap(); // Remove the temporary directory so that TempDir sees // an error on drop diff --git a/src/test/run-pass/terminate-in-initializer.rs b/src/test/run-pass/terminate-in-initializer.rs index 185edb02cca..bef9efa9eb6 100644 --- a/src/test/run-pass/terminate-in-initializer.rs +++ b/src/test/run-pass/terminate-in-initializer.rs @@ -12,7 +12,7 @@ // Issue #787 // Don't try to clean up uninitialized locals -use std::thread::Thread; +use std::thread; fn test_break() { loop { let _x: Box = break; } } @@ -22,13 +22,13 @@ fn test_ret() { let _x: Box = return; } fn test_panic() { fn f() { let _x: Box = panic!(); } - Thread::scoped(move|| f() ).join().err().unwrap(); + thread::spawn(move|| f() ).join().err().unwrap(); } fn test_panic_indirect() { fn f() -> ! { panic!(); } fn g() { let _x: Box = f(); } - Thread::scoped(move|| g() ).join().err().unwrap(); + thread::spawn(move|| g() ).join().err().unwrap(); } pub fn main() { -- cgit 1.4.1-3-g733a5