aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sync
diff options
context:
space:
mode:
authorFenrir <[email protected]>2018-08-19 17:48:00 -0600
committerFenrir <[email protected]>2018-08-19 17:56:18 -0600
commit5d28bfcfd6086c3328837de9695099ea39048d0d (patch)
treea514fde042ff2a504a03305bfe0894ff8cd8d47e /ctr-std/src/sync
parentUpdate for latest nightly 2018-06-09 (#70) (diff)
downloadctru-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.rs2
-rw-r--r--ctr-std/src/sync/mpsc/mod.rs40
-rw-r--r--ctr-std/src/sync/mpsc/select.rs2
-rw-r--r--ctr-std/src/sync/mutex.rs4
-rw-r--r--ctr-std/src/sync/once.rs40
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.