about summary refs log tree commit diff
path: root/src/libstd/thread
diff options
context:
space:
mode:
authorAaron Turon <aturon@mozilla.com>2015-04-13 12:08:20 -0700
committerAaron Turon <aturon@mozilla.com>2015-04-13 12:15:28 -0700
commit6399bb425b3a82111cd554737f194c95b8f6bad5 (patch)
treef1799d53b1c70ba745ac6c0d82da3fe6d2b26b23 /src/libstd/thread
parent588d37c653ddac491c2c1cb8974f56781533b173 (diff)
downloadrust-6399bb425b3a82111cd554737f194c95b8f6bad5.tar.gz
rust-6399bb425b3a82111cd554737f194c95b8f6bad5.zip
De-stabilize `thread::scoped` and friends
Issue #24292 demonstrates that the `scoped` API as currently offered can
be memory-unsafe: the `JoinGuard` can be moved into a context that will
fail to execute destructors prior to the stack frame being popped (for
example, by creating an `Rc` cycle).

This commit reverts the APIs to `unstable` status while a long-term
solution is worked out.

(There are several possible ways to address this issue; it's not a
fundamental problem with the `scoped` idea, but rather an indication
that Rust doesn't currently provide a good way to ensure that
destructors are run within a particular stack frame.)

[breaking-change]
Diffstat (limited to 'src/libstd/thread')
-rw-r--r--src/libstd/thread/mod.rs12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 0e5fee27ffe..23991102650 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -274,7 +274,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
     {
@@ -387,7 +388,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
 {
@@ -674,7 +676,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 +709,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 {