about summary refs log tree commit diff
path: root/src/libstd/thread
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-14 10:59:55 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-14 10:59:55 -0700
commitb9d9a376ea8843f46ccf9f043dbffa5ac2d1c073 (patch)
tree94aa404c31d33f17e0fac67b1ea8e7e6a0b30946 /src/libstd/thread
parentae7959d298c95d5ffdeae8e7c3f3659d7fc28cdb (diff)
parenta9fd41e1f984fdfecb78ba9570bb159854c58b16 (diff)
downloadrust-b9d9a376ea8843f46ccf9f043dbffa5ac2d1c073.tar.gz
rust-b9d9a376ea8843f46ccf9f043dbffa5ac2d1c073.zip
rollup merge of #24385: aturon/unstable-scoped
Conflicts:
	src/libstd/thread/mod.rs
	src/test/bench/shootout-mandelbrot.rs
	src/test/bench/shootout-reverse-complement.rs
	src/test/run-pass/capturing-logging.rs
	src/test/run-pass/issue-9396.rs
	src/test/run-pass/tcp-accept-stress.rs
	src/test/run-pass/tcp-connect-timeouts.rs
	src/test/run-pass/tempfile.rs
Diffstat (limited to 'src/libstd/thread')
-rw-r--r--src/libstd/thread/mod.rs55
1 files changed, 41 insertions, 14 deletions
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index a073f669d26..4fd0340f09a 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -67,13 +67,33 @@
 //! thread. This means that it can outlive its parent (the thread that spawned
 //! it), unless this parent is the main thread.
 //!
+//! The parent thread can also wait on the completion of the child
+//! thread; a call to `spawn` produces a `JoinHandle`, which provides
+//! a `join` method for waiting:
+//!
+//! ```rust
+//! use std::thread;
+//!
+//! let child = thread::spawn(move || {
+//!     // some work here
+//! });
+//! // some work here
+//! let res = child.join();
+//! ```
+//!
+//! The `join` method returns a `Result` containing `Ok` of the final
+//! value produced by the child thread, or `Err` of the value given to
+//! a call to `panic!` if the child panicked.
+//!
 //! ## Scoped threads
 //!
-//! Often a parent thread uses a child thread to perform some particular task,
-//! and at some point must wait for the child to complete before continuing.
-//! For this scenario, use the `thread::scoped` function:
+//! The `spawn` method does not allow the child and parent threads to
+//! share any stack data, since that is not safe in general. However,
+//! `scoped` makes it possible to share the parent's stack by forcing
+//! a join before any relevant stack frames are popped:
 //!
 //! ```rust
+//! # #![feature(scoped)]
 //! use std::thread;
 //!
 //! let guard = thread::scoped(move || {
@@ -253,8 +273,8 @@ impl Builder {
     /// `io::Result` to capture any failure to create the thread at
     /// the OS level.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
-        F: FnOnce(), F: Send + 'static
+    pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
+        F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
     {
         self.spawn_inner(Box::new(f)).map(|i| JoinHandle(i))
     }
@@ -274,7 +294,8 @@ impl Builder {
     /// 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")]
+    #[unstable(feature = "scoped",
+               reason = "memory unsafe if destructor is avoided, see #24292")]
     pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
         T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
     {
@@ -370,7 +391,9 @@ impl Builder {
 /// Panics 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: F) -> JoinHandle where F: FnOnce(), F: Send + 'static {
+pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
+    F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
+{
     Builder::new().spawn(f).unwrap()
 }
 
@@ -387,7 +410,8 @@ pub fn spawn<F>(f: F) -> JoinHandle where F: FnOnce(), F: Send + 'static {
 ///
 /// Panics if the OS fails to create a thread; use `Builder::scoped`
 /// to recover from such errors.
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "scoped",
+           reason = "memory unsafe if destructor is avoided, see #24292")]
 pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
     T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
 {
@@ -635,9 +659,9 @@ impl<T> JoinInner<T> {
 /// handle: the ability to join a child thread is a uniquely-owned
 /// permission.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct JoinHandle(JoinInner<()>);
+pub struct JoinHandle<T>(JoinInner<T>);
 
-impl JoinHandle {
+impl<T> JoinHandle<T> {
     /// Extracts a handle to the underlying thread
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn thread(&self) -> &Thread {
@@ -649,13 +673,14 @@ impl JoinHandle {
     /// 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<()> {
+    pub fn join(mut self) -> Result<T> {
         self.0.join()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Drop for JoinHandle {
+#[unsafe_destructor]
+impl<T> Drop for JoinHandle<T> {
     fn drop(&mut self) {
         if !self.0.joined {
             unsafe { imp::detach(self.0.native) }
@@ -674,7 +699,8 @@ impl Drop for JoinHandle {
 /// handle: the ability to join a child thread is a uniquely-owned
 /// permission.
 #[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "scoped",
+           reason = "memory unsafe if destructor is avoided, see #24292")]
 pub struct JoinGuard<'a, T: Send + 'a> {
     inner: JoinInner<T>,
     _marker: PhantomData<&'a T>,
@@ -706,7 +732,8 @@ impl<'a, T: Send + 'a> JoinGuard<'a, T> {
 }
 
 #[unsafe_destructor]
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "scoped",
+           reason = "memory unsafe if destructor is avoided, see #24292")]
 impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
     fn drop(&mut self) {
         if !self.inner.joined {