diff options
| author | Fenrir <[email protected]> | 2018-08-19 17:48:00 -0600 |
|---|---|---|
| committer | Fenrir <[email protected]> | 2018-08-19 17:56:18 -0600 |
| commit | 5d28bfcfd6086c3328837de9695099ea39048d0d (patch) | |
| tree | a514fde042ff2a504a03305bfe0894ff8cd8d47e /ctr-std/src/sync | |
| parent | Update for latest nightly 2018-06-09 (#70) (diff) | |
| download | ctru-rs-5d28bfcfd6086c3328837de9695099ea39048d0d.tar.xz ctru-rs-5d28bfcfd6086c3328837de9695099ea39048d0d.zip | |
Update for nightly-2018-08-18
Diffstat (limited to 'ctr-std/src/sync')
| -rw-r--r-- | ctr-std/src/sync/mod.rs | 2 | ||||
| -rw-r--r-- | ctr-std/src/sync/mpsc/mod.rs | 40 | ||||
| -rw-r--r-- | ctr-std/src/sync/mpsc/select.rs | 2 | ||||
| -rw-r--r-- | ctr-std/src/sync/mutex.rs | 4 | ||||
| -rw-r--r-- | ctr-std/src/sync/once.rs | 40 |
5 files changed, 63 insertions, 25 deletions
diff --git a/ctr-std/src/sync/mod.rs b/ctr-std/src/sync/mod.rs index 642b284..e12ef8d 100644 --- a/ctr-std/src/sync/mod.rs +++ b/ctr-std/src/sync/mod.rs @@ -18,7 +18,7 @@ #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -pub use alloc_crate::arc::{Arc, Weak}; +pub use alloc_crate::sync::{Arc, Weak}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; diff --git a/ctr-std/src/sync/mpsc/mod.rs b/ctr-std/src/sync/mpsc/mod.rs index 2dd3aeb..59cf741 100644 --- a/ctr-std/src/sync/mpsc/mod.rs +++ b/ctr-std/src/sync/mpsc/mod.rs @@ -689,7 +689,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> { /// only one [`Receiver`] is supported. /// /// If the [`Receiver`] is disconnected while trying to [`send`] with the -/// [`Sender`], the [`send`] method will return a [`SendError`]. Similarly, If the +/// [`Sender`], the [`send`] method will return a [`SendError`]. Similarly, if the /// [`Sender`] is disconnected while trying to [`recv`], the [`recv`] method will /// return a [`RecvError`]. /// @@ -1247,6 +1247,34 @@ impl<T> Receiver<T> { /// [`SyncSender`]: struct.SyncSender.html /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err /// + /// # Known Issues + /// + /// There is currently a known issue (see [`#39364`]) that causes `recv_timeout` + /// to panic unexpectedly with the following example: + /// + /// ```no_run + /// use std::sync::mpsc::channel; + /// use std::thread; + /// use std::time::Duration; + /// + /// let (tx, rx) = channel::<String>(); + /// + /// thread::spawn(move || { + /// let d = Duration::from_millis(10); + /// loop { + /// println!("recv"); + /// let _r = rx.recv_timeout(d); + /// } + /// }); + /// + /// thread::sleep(Duration::from_millis(100)); + /// let _c1 = tx.clone(); + /// + /// thread::sleep(Duration::from_secs(1)); + /// ``` + /// + /// [`#39364`]: https://github.com/rust-lang/rust/issues/39364 + /// /// # Examples /// /// Successfully receiving value before encountering timeout: @@ -1638,7 +1666,7 @@ impl<T: Send> error::Error for SendError<T> { "sending on a closed channel" } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1681,7 +1709,7 @@ impl<T: Send> error::Error for TrySendError<T> { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1709,7 +1737,7 @@ impl error::Error for RecvError { "receiving on a closed channel" } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1742,7 +1770,7 @@ impl error::Error for TryRecvError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } @@ -1783,7 +1811,7 @@ impl error::Error for RecvTimeoutError { } } - fn cause(&self) -> Option<&error::Error> { + fn cause(&self) -> Option<&dyn error::Error> { None } } diff --git a/ctr-std/src/sync/mpsc/select.rs b/ctr-std/src/sync/mpsc/select.rs index 9310dad..a7a284c 100644 --- a/ctr-std/src/sync/mpsc/select.rs +++ b/ctr-std/src/sync/mpsc/select.rs @@ -93,7 +93,7 @@ pub struct Handle<'rx, T:Send+'rx> { next: *mut Handle<'static, ()>, prev: *mut Handle<'static, ()>, added: bool, - packet: &'rx (Packet+'rx), + packet: &'rx (dyn Packet+'rx), // due to our fun transmutes, we be sure to place this at the end. (nothing // previous relies on T) diff --git a/ctr-std/src/sync/mutex.rs b/ctr-std/src/sync/mutex.rs index f3503b0..e5a4106 100644 --- a/ctr-std/src/sync/mutex.rs +++ b/ctr-std/src/sync/mutex.rs @@ -227,7 +227,7 @@ impl<T: ?Sized> Mutex<T> { #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> LockResult<MutexGuard<T>> { unsafe { - self.inner.lock(); + self.inner.raw_lock(); MutexGuard::new(self) } } @@ -454,7 +454,7 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { fn drop(&mut self) { unsafe { self.__lock.poison.done(&self.__poison); - self.__lock.inner.unlock(); + self.__lock.inner.raw_unlock(); } } } diff --git a/ctr-std/src/sync/once.rs b/ctr-std/src/sync/once.rs index 7eb7be2..f6cb8be 100644 --- a/ctr-std/src/sync/once.rs +++ b/ctr-std/src/sync/once.rs @@ -31,12 +31,10 @@ // initialization closure panics, the Once enters a "poisoned" state which means // that all future calls will immediately panic as well. // -// So to implement this, one might first reach for a `StaticMutex`, but those -// unfortunately need to be deallocated (e.g. call `destroy()`) to free memory -// on all OSes (some of the BSDs allocate memory for mutexes). It also gets a -// lot harder with poisoning to figure out when the mutex needs to be -// deallocated because it's not after the closure finishes, but after the first -// successful closure finishes. +// So to implement this, one might first reach for a `Mutex`, but those cannot +// be put into a `static`. It also gets a lot harder with poisoning to figure +// out when the mutex needs to be deallocated because it's not after the closure +// finishes, but after the first successful closure finishes. // // All in all, this is instead implemented with atomics and lock-free // operations! Whee! Each `Once` has one word of atomic state, and this state is @@ -149,9 +147,9 @@ struct Waiter { // Helper struct used to clean up after a closure call with a `Drop` // implementation to also run on panic. -struct Finish { +struct Finish<'a> { panicked: bool, - me: &'static Once, + me: &'a Once, } impl Once { @@ -178,6 +176,10 @@ impl Once { /// happens-before relation between the closure and code executing after the /// return). /// + /// If the given closure recusively invokes `call_once` on the same `Once` + /// instance the exact behavior is not specified, allowed outcomes are + /// a panic or a deadlock. + /// /// # Examples /// /// ``` @@ -218,9 +220,13 @@ impl Once { /// /// [poison]: struct.Mutex.html#poisoning #[stable(feature = "rust1", since = "1.0.0")] - pub fn call_once<F>(&'static self, f: F) where F: FnOnce() { + pub fn call_once<F>(&self, f: F) where F: FnOnce() { // Fast path, just see if we've completed initialization. - if self.state.load(Ordering::SeqCst) == COMPLETE { + // An `Acquire` load is enough because that makes all the initialization + // operations visible to us. The cold path uses SeqCst consistently + // because the performance difference really does not matter there, + // and SeqCst minimizes the chances of something going wrong. + if self.state.load(Ordering::Acquire) == COMPLETE { return } @@ -275,9 +281,13 @@ impl Once { /// INIT.call_once(|| {}); /// ``` #[unstable(feature = "once_poison", issue = "33577")] - pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) { + pub fn call_once_force<F>(&self, f: F) where F: FnOnce(&OnceState) { // same as above, just with a different parameter to `call_inner`. - if self.state.load(Ordering::SeqCst) == COMPLETE { + // An `Acquire` load is enough because that makes all the initialization + // operations visible to us. The cold path uses SeqCst consistently + // because the performance difference really does not matter there, + // and SeqCst minimizes the chances of something going wrong. + if self.state.load(Ordering::Acquire) == COMPLETE { return } @@ -299,9 +309,9 @@ impl Once { // currently no way to take an `FnOnce` and call it via virtual dispatch // without some allocation overhead. #[cold] - fn call_inner(&'static self, + fn call_inner(&self, ignore_poisoning: bool, - init: &mut FnMut(bool)) { + init: &mut dyn FnMut(bool)) { let mut state = self.state.load(Ordering::SeqCst); 'outer: loop { @@ -390,7 +400,7 @@ impl fmt::Debug for Once { } } -impl Drop for Finish { +impl<'a> Drop for Finish<'a> { fn drop(&mut self) { // Swap out our state with however we finished. We should only ever see // an old state which was RUNNING. |