diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-04-14 10:59:55 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-04-14 10:59:55 -0700 |
| commit | b9d9a376ea8843f46ccf9f043dbffa5ac2d1c073 (patch) | |
| tree | 94aa404c31d33f17e0fac67b1ea8e7e6a0b30946 /src/libstd/thread | |
| parent | ae7959d298c95d5ffdeae8e7c3f3659d7fc28cdb (diff) | |
| parent | a9fd41e1f984fdfecb78ba9570bb159854c58b16 (diff) | |
| download | rust-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.rs | 55 |
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 { |
