diff options
| author | bors <bors@rust-lang.org> | 2014-12-19 08:28:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-12-19 08:28:52 +0000 |
| commit | 0efafac398ff7f28c5f0fe756c15b9008b3e0534 (patch) | |
| tree | 2e8279b94829b65868049d2e3df0b9a6c3365a8f /src/libstd/sync | |
| parent | 6bdce25e155d846bb9252fa4a18baef7e74cf8bf (diff) | |
| parent | 903c5a8f69714382ec9fc22745f902c3e219cb68 (diff) | |
| download | rust-0efafac398ff7f28c5f0fe756c15b9008b3e0534.tar.gz rust-0efafac398ff7f28c5f0fe756c15b9008b3e0534.zip | |
auto merge of #19654 : aturon/rust/merge-rt, r=alexcrichton
This PR substantially narrows the notion of a "runtime" in Rust, and allows calling into Rust code directly without any setup or teardown. After this PR, the basic "runtime support" in Rust will consist of: * Unwinding and backtrace support * Stack guards Other support, such as helper threads for timers or the notion of a "current thread" are initialized automatically upon first use. When using Rust in an embedded context, it should now be possible to call a Rust function directly as a C function with absolutely no setup, though in that case panics will cause the process to abort. In this regard, the C/Rust interface will look much like the C/C++ interface. In more detail, this PR: * Merges `librustrt` back into `std::rt`, undoing the facade. While doing so, it removes a substantial amount of redundant functionality (such as mutexes defined in the `rt` module). Code using `librustrt` can now call into `std::rt` to e.g. start executing Rust code with unwinding support. * Allows all runtime data to be initialized lazily, including the "current thread", the "at_exit" infrastructure, and the "args" storage. * Deprecates and largely removes `std::task` along with the widespread requirement that there be a "current task" for many APIs in `std`. The entire task infrastructure is replaced with `std::thread`, which provides a more standard API for manipulating and creating native OS threads. In particular, it's possible to join on a created thread, and to get a handle to the currently-running thread. In addition, threads are equipped with some basic blocking support in the form of `park`/`unpark` operations (following a tradition in some OSes as well as the JVM). See the `std::thread` documentation for more details. * Channels are refactored to use a new internal blocking infrastructure that itself sits on top of `park`/`unpark`. One important change here is that a Rust program ends when its main thread does, following most threading models. On the other hand, threads will often be created with an RAII-style join handle that will re-institute blocking semantics naturally (and with finer control). This is very much a: [breaking-change] Closes #18000 r? @alexcrichton
Diffstat (limited to 'src/libstd/sync')
| -rw-r--r-- | src/libstd/sync/atomic.rs | 10 | ||||
| -rw-r--r-- | src/libstd/sync/barrier.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sync/condvar.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sync/future.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sync/mutex.rs | 15 | ||||
| -rw-r--r-- | src/libstd/sync/once.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sync/poison.rs | 18 | ||||
| -rw-r--r-- | src/libstd/sync/rwlock.rs | 34 | ||||
| -rw-r--r-- | src/libstd/sync/task_pool.rs | 7 |
9 files changed, 49 insertions, 56 deletions
diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs index fe5b962fa4b..26778ef70b3 100644 --- a/src/libstd/sync/atomic.rs +++ b/src/libstd/sync/atomic.rs @@ -42,14 +42,15 @@ //! ``` //! use std::sync::Arc; //! use std::sync::atomic::{AtomicUint, SeqCst}; +//! use std::thread::Thread; //! //! fn main() { //! let spinlock = Arc::new(AtomicUint::new(1)); //! //! let spinlock_clone = spinlock.clone(); -//! spawn(move|| { +//! Thread::spawn(move|| { //! spinlock_clone.store(0, SeqCst); -//! }); +//! }).detach(); //! //! // Wait for the other task to release the lock //! while spinlock.load(SeqCst) != 0 {} @@ -61,6 +62,7 @@ //! ``` //! use std::sync::Arc; //! use std::sync::atomic::{AtomicOption, SeqCst}; +//! use std::thread::Thread; //! //! fn main() { //! struct BigObject; @@ -68,14 +70,14 @@ //! let shared_big_object = Arc::new(AtomicOption::empty()); //! //! let shared_big_object_clone = shared_big_object.clone(); -//! spawn(move|| { +//! Thread::spawn(move|| { //! let unwrapped_big_object = shared_big_object_clone.take(SeqCst); //! if unwrapped_big_object.is_some() { //! println!("got a big object from another task"); //! } else { //! println!("other task hasn't sent big object yet"); //! } -//! }); +//! }).detach(); //! //! shared_big_object.swap(box BigObject, SeqCst); //! } diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index 1b8574604a0..6573d9273ce 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -15,17 +15,18 @@ use sync::{Mutex, Condvar}; /// /// ```rust /// use std::sync::{Arc, Barrier}; +/// use std::thread::Thread; /// /// let barrier = Arc::new(Barrier::new(10)); /// for _ in range(0u, 10) { /// let c = barrier.clone(); /// // The same messages will be printed together. /// // You will NOT see any interleaving. -/// spawn(move|| { +/// Thread::spawn(move|| { /// println!("before wait"); /// c.wait(); /// println!("after wait"); -/// }); +/// }).detach(); /// } /// ``` pub struct Barrier { diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 3bdab261e19..be27c06b83c 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -36,17 +36,18 @@ use time::Duration; /// /// ``` /// use std::sync::{Arc, Mutex, Condvar}; +/// use std::thread::Thread; /// /// let pair = Arc::new((Mutex::new(false), Condvar::new())); /// let pair2 = pair.clone(); /// /// // Inside of our lock, spawn a new thread, and then wait for it to start -/// spawn(move|| { +/// Thread::spawn(move|| { /// let &(ref lock, ref cvar) = &*pair2; /// let mut started = lock.lock(); /// *started = true; /// cvar.notify_one(); -/// }); +/// }).detach(); /// /// // wait for the thread to start up /// let &(ref lock, ref cvar) = &*pair; @@ -362,4 +363,3 @@ mod tests { } } - diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index e5a1e09967c..5e9d234c642 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -29,8 +29,8 @@ use core::mem::replace; use self::FutureState::*; use comm::{Receiver, channel}; -use task::spawn; use thunk::{Thunk}; +use thread::Thread; /// A type encapsulating the result of a computation which may not be complete pub struct Future<A> { @@ -139,10 +139,10 @@ impl<A:Send> Future<A> { let (tx, rx) = channel(); - spawn(move |:| { + Thread::spawn(move |:| { // Don't panic if the other end has hung up let _ = tx.send_opt(blk()); - }); + }).detach(); Future::from_receiver(rx) } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 33f8d254c71..4829be569cc 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -35,6 +35,7 @@ use sys_common::mutex as sys; /// /// ```rust /// use std::sync::{Arc, Mutex}; +/// use std::thread::Thread; /// const N: uint = 10; /// /// // Spawn a few threads to increment a shared variable (non-atomically), and @@ -47,7 +48,7 @@ use sys_common::mutex as sys; /// let (tx, rx) = channel(); /// for _ in range(0u, 10) { /// let (data, tx) = (data.clone(), tx.clone()); -/// spawn(move|| { +/// Thread::spawn(move|| { /// // The shared static can only be accessed once the lock is held. /// // Our non-atomic increment is safe because we're the only thread /// // which can access the shared state when the lock is held. @@ -57,7 +58,7 @@ use sys_common::mutex as sys; /// tx.send(()); /// } /// // the lock is unlocked here when `data` goes out of scope. -/// }); +/// }).detach(); /// } /// /// rx.recv(); @@ -274,7 +275,7 @@ impl Drop for StaticMutexGuard { mod test { use prelude::*; - use task; + use thread::Thread; use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar}; #[test] @@ -386,10 +387,10 @@ mod test { fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| { + let _ = Thread::spawn(move|| { let lock = arc2.lock(); assert_eq!(*lock, 2); - }); + }).join(); let lock = arc.lock(); assert_eq!(*lock, 1); } @@ -414,7 +415,7 @@ mod test { fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(Mutex::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| -> () { + let _ = Thread::spawn(move|| -> () { struct Unwinder { i: Arc<Mutex<int>>, } @@ -425,7 +426,7 @@ mod test { } let _u = Unwinder { i: arc2 }; panic!(); - }); + }).join(); let lock = arc.lock(); assert_eq!(*lock, 2); } diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 263937c5cbe..a43f822e351 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -121,7 +121,7 @@ impl Once { mod test { use prelude::*; - use task; + use thread::Thread; use super::{ONCE_INIT, Once}; #[test] @@ -143,7 +143,7 @@ mod test { for _ in range(0u, 10) { let tx = tx.clone(); spawn(move|| { - for _ in range(0u, 4) { task::deschedule() } + for _ in range(0u, 4) { Thread::yield_now() } unsafe { O.doit(|| { assert!(!run); diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index ee151556620..ad08e9873fa 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -8,21 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use option::Option::None; -use rustrt::task::Task; -use rustrt::local::Local; +use thread::Thread; pub struct Flag { pub failed: bool } impl Flag { pub fn borrow(&mut self) -> Guard { - Guard { flag: &mut self.failed, failing: failing() } + Guard { flag: &mut self.failed, panicking: Thread::panicking() } } } pub struct Guard<'a> { flag: &'a mut bool, - failing: bool, + panicking: bool, } impl<'a> Guard<'a> { @@ -33,16 +31,8 @@ impl<'a> Guard<'a> { } pub fn done(&mut self) { - if !self.failing && failing() { + if !self.panicking && Thread::panicking() { *self.flag = true; } } } - -fn failing() -> bool { - if Local::exists(None::<Task>) { - Local::borrow(None::<Task>).unwinder.unwinding() - } else { - false - } -} diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index b6d6aa989c5..07b2f2cf541 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -356,7 +356,7 @@ mod tests { use prelude::*; use rand::{mod, Rng}; - use task; + use thread::Thread; use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT}; #[test] @@ -409,10 +409,10 @@ mod tests { fn test_rw_arc_poison_wr() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| { + let _ = Thread::spawn(move|| { let lock = arc2.write(); assert_eq!(*lock, 2); - }); + }).join(); let lock = arc.read(); assert_eq!(*lock, 1); } @@ -422,10 +422,10 @@ mod tests { fn test_rw_arc_poison_ww() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| { + let _ = Thread::spawn(move|| { let lock = arc2.write(); assert_eq!(*lock, 2); - }); + }).join(); let lock = arc.write(); assert_eq!(*lock, 1); } @@ -434,10 +434,10 @@ mod tests { fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| { + let _ = Thread::spawn(move|| { let lock = arc2.read(); assert_eq!(*lock, 2); - }); + }).join(); let lock = arc.read(); assert_eq!(*lock, 1); } @@ -445,10 +445,10 @@ mod tests { fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| { + let _ = Thread::spawn(move|| { let lock = arc2.read(); assert_eq!(*lock, 2); - }); + }).join(); let lock = arc.write(); assert_eq!(*lock, 1); } @@ -459,30 +459,30 @@ mod tests { let arc2 = arc.clone(); let (tx, rx) = channel(); - task::spawn(move|| { + Thread::spawn(move|| { let mut lock = arc2.write(); for _ in range(0u, 10) { let tmp = *lock; *lock = -1; - task::deschedule(); + Thread::yield_now(); *lock = tmp + 1; } tx.send(()); - }); + }).detach(); // Readers try to catch the writer in the act let mut children = Vec::new(); for _ in range(0u, 5) { let arc3 = arc.clone(); - children.push(task::try_future(move|| { + children.push(Thread::spawn(move|| { let lock = arc3.read(); assert!(*lock >= 0); })); } // Wait for children to pass their asserts - for r in children.iter_mut() { - assert!(r.get_ref().is_ok()); + for r in children.into_iter() { + assert!(r.join().is_ok()); } // Wait for writer to finish @@ -495,7 +495,7 @@ mod tests { fn test_rw_arc_access_in_unwind() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = task::try(move|| -> () { + let _ = Thread::spawn(move|| -> () { struct Unwinder { i: Arc<RWLock<int>>, } @@ -507,7 +507,7 @@ mod tests { } let _u = Unwinder { i: arc2 }; panic!(); - }); + }).join(); let lock = arc.read(); assert_eq!(*lock, 2); } diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index fa5b62a202b..793825f1b08 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -12,7 +12,7 @@ use core::prelude::*; -use task::{spawn}; +use thread::Thread; use comm::{channel, Sender, Receiver}; use sync::{Arc, Mutex}; use thunk::Thunk; @@ -105,7 +105,7 @@ impl TaskPool { } fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) { - spawn(move |:| { + Thread::spawn(move |:| { // Will spawn a new task on panic unless it is cancelled. let sentinel = Sentinel::new(&jobs); @@ -126,7 +126,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) { } sentinel.cancel(); - }) + }).detach(); } #[cfg(test)] @@ -206,4 +206,3 @@ mod test { waiter.wait(); } } - |
