summary refs log tree commit diff
path: root/src/libstd/io
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-06 15:38:38 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-06 15:38:38 -0800
commit36f5d122b80682de473aeda2e20f14b6ceb86d74 (patch)
tree84fff634fa8759f4ef8d90651f8a9c242fb8ea51 /src/libstd/io
parent0631b466c23ffdb1edb2997a8da2702cfe6fcd4a (diff)
parentcaca9b2e7109a148d100a3c6851241d3815da3db (diff)
downloadrust-36f5d122b80682de473aeda2e20f14b6ceb86d74.tar.gz
rust-36f5d122b80682de473aeda2e20f14b6ceb86d74.zip
rollup merge of #20615: aturon/stab-2-thread
This commit takes a first pass at stabilizing `std::thread`:

* It removes the `detach` method in favor of two constructors -- `spawn`
  for detached threads, `scoped` for "scoped" (i.e., must-join)
  threads. This addresses some of the surprise/frustrating debug
  sessions with the previous API, in which `spawn` produced a guard that
  on destruction joined the thread (unless `detach` was called).

  The reason to have the division in part is that `Send` will soon not
  imply `'static`, which means that `scoped` thread creation can take a
  closure over *shared stack data* of the parent thread. On the other
  hand, this means that the parent must not pop the relevant stack
  frames while the child thread is running. The `JoinGuard` is used to
  prevent this from happening by joining on drop (if you have not
  already explicitly `join`ed.) The APIs around `scoped` are
  future-proofed for the `Send` changes by taking an additional lifetime
  parameter. With the current definition of `Send`, this is forced to be
  `'static`, but when `Send` changes these APIs will gain their full
  flexibility immediately.

  Threads that are `spawn`ed, on the other hand, are detached from the
  start and do not yield an RAII guard.

  The hope is that, by making `scoped` an explicit opt-in with a very
  suggestive name, it will be drastically less likely to be caught by a
  surprising deadlock due to an implicit join at the end of a scope.

* The module itself is marked stable.

* Existing methods other than `spawn` and `scoped` are marked stable.

The migration path is:

```rust
Thread::spawn(f).detached()
```

becomes

```rust
Thread::spawn(f)
```

while

```rust
let res = Thread::spawn(f);
res.join()
```

becomes

```rust
let res = Thread::scoped(f);
res.join()
```

[breaking-change]
Diffstat (limited to 'src/libstd/io')
-rw-r--r--src/libstd/io/comm_adapters.rs6
-rw-r--r--src/libstd/io/mod.rs10
-rw-r--r--src/libstd/io/net/pipe.rs12
-rw-r--r--src/libstd/io/net/tcp.rs26
-rw-r--r--src/libstd/io/process.rs2
-rw-r--r--src/libstd/io/timer.rs6
6 files changed, 33 insertions, 29 deletions
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
index bcd0c09b77d..bce097e17ef 100644
--- a/src/libstd/io/comm_adapters.rs
+++ b/src/libstd/io/comm_adapters.rs
@@ -173,7 +173,7 @@ mod test {
           tx.send(vec![3u8, 4u8]).unwrap();
           tx.send(vec![5u8, 6u8]).unwrap();
           tx.send(vec![7u8, 8u8]).unwrap();
-        }).detach();
+        });
 
         let mut reader = ChanReader::new(rx);
         let mut buf = [0u8; 3];
@@ -216,7 +216,7 @@ mod test {
           tx.send(b"rld\nhow ".to_vec()).unwrap();
           tx.send(b"are you?".to_vec()).unwrap();
           tx.send(b"".to_vec()).unwrap();
-        }).detach();
+        });
 
         let mut reader = ChanReader::new(rx);
 
@@ -235,7 +235,7 @@ mod test {
         writer.write_be_u32(42).unwrap();
 
         let wanted = vec![0u8, 0u8, 0u8, 42u8];
-        let got = match Thread::spawn(move|| { rx.recv().unwrap() }).join() {
+        let got = match Thread::scoped(move|| { rx.recv().unwrap() }).join() {
             Ok(got) => got,
             Err(_) => panic!(),
         };
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 42f72fa3259..9ef9081bc3c 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -120,10 +120,12 @@
 //!     for stream in acceptor.incoming() {
 //!         match stream {
 //!             Err(e) => { /* connection failed */ }
-//!             Ok(stream) => Thread::spawn(move|| {
-//!                 // connection succeeded
-//!                 handle_client(stream)
-//!             }).detach()
+//!             Ok(stream) => {
+//!                 Thread::spawn(move|| {
+//!                     // connection succeeded
+//!                     handle_client(stream)
+//!                 });
+//!             }
 //!         }
 //!     }
 //!
diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs
index 738c70412f7..29295b5751c 100644
--- a/src/libstd/io/net/pipe.rs
+++ b/src/libstd/io/net/pipe.rs
@@ -608,7 +608,7 @@ mod tests {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut b = [0];
         let mut s = UnixStream::connect(&addr).unwrap();
@@ -645,7 +645,7 @@ mod tests {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = UnixStream::connect(&addr).unwrap();
         let s2 = s.clone();
@@ -672,7 +672,7 @@ mod tests {
             rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         s.set_timeout(Some(20));
@@ -716,7 +716,7 @@ mod tests {
                 }
             }
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         s.set_read_timeout(Some(20));
@@ -739,7 +739,7 @@ mod tests {
             rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         s.set_write_timeout(Some(20));
@@ -766,7 +766,7 @@ mod tests {
             rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         let s2 = s.clone();
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index 3e59aaa05ef..b1762ff26fc 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -146,7 +146,7 @@ impl TcpStream {
     ///     timer::sleep(Duration::seconds(1));
     ///     let mut stream = stream2;
     ///     stream.close_read();
-    /// }).detach();
+    /// });
     ///
     /// // wait for some data, will get canceled after one second
     /// let mut buf = [0];
@@ -295,10 +295,12 @@ impl sys_common::AsInner<TcpStreamImp> for TcpStream {
 /// for stream in acceptor.incoming() {
 ///     match stream {
 ///         Err(e) => { /* connection failed */ }
-///         Ok(stream) => Thread::spawn(move|| {
-///             // connection succeeded
-///             handle_client(stream)
-///         }).detach()
+///         Ok(stream) => {
+///             Thread::spawn(move|| {
+///                 // connection succeeded
+///                 handle_client(stream)
+///             });
+///         }
 ///     }
 /// }
 ///
@@ -432,7 +434,7 @@ impl TcpAcceptor {
     ///             Err(e) => panic!("unexpected error: {}", e),
     ///         }
     ///     }
-    /// }).detach();
+    /// });
     ///
     /// # fn wait_for_sigint() {}
     /// // Now that our accept loop is running, wait for the program to be
@@ -1186,7 +1188,7 @@ mod test {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv().unwrap();
-        }).detach();
+        });
 
         let mut b = [0];
         let mut s = TcpStream::connect(addr).unwrap();
@@ -1223,7 +1225,7 @@ mod test {
             let mut a = a;
             let _s = a.accept().unwrap();
             let _ = rx.recv().unwrap();
-        }).detach();
+        });
 
         let mut s = TcpStream::connect(addr).unwrap();
         let s2 = s.clone();
@@ -1250,7 +1252,7 @@ mod test {
             rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         s.set_timeout(Some(20));
@@ -1289,7 +1291,7 @@ mod test {
                 }
             }
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         s.set_read_timeout(Some(20));
@@ -1312,7 +1314,7 @@ mod test {
             rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         s.set_write_timeout(Some(20));
@@ -1340,7 +1342,7 @@ mod test {
             rx.recv().unwrap();
             assert_eq!(s.write(&[0]), Ok(()));
             let _ = rx.recv();
-        }).detach();
+        });
 
         let mut s = a.accept().unwrap();
         let s2 = s.clone();
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
index efb57341620..55df6330dd3 100644
--- a/src/libstd/io/process.rs
+++ b/src/libstd/io/process.rs
@@ -720,7 +720,7 @@ impl Process {
                     Thread::spawn(move |:| {
                         let mut stream = stream;
                         tx.send(stream.read_to_end()).unwrap();
-                    }).detach();
+                    });
                 }
                 None => tx.send(Ok(Vec::new())).unwrap()
             }
diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs
index e073f76af82..8a0445be471 100644
--- a/src/libstd/io/timer.rs
+++ b/src/libstd/io/timer.rs
@@ -358,7 +358,7 @@ mod test {
 
         Thread::spawn(move|| {
             let _ = timer_rx.recv();
-        }).detach();
+        });
 
         // when we drop the TimerWatcher we're going to destroy the channel,
         // which must wake up the task on the other end
@@ -372,7 +372,7 @@ mod test {
 
         Thread::spawn(move|| {
             let _ = timer_rx.recv();
-        }).detach();
+        });
 
         timer.oneshot(Duration::milliseconds(1));
     }
@@ -385,7 +385,7 @@ mod test {
 
         Thread::spawn(move|| {
             let _ = timer_rx.recv();
-        }).detach();
+        });
 
         timer.sleep(Duration::milliseconds(1));
     }