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/thread/mod.rs | |
| 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/thread/mod.rs')
| -rw-r--r-- | ctr-std/src/thread/mod.rs | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/ctr-std/src/thread/mod.rs b/ctr-std/src/thread/mod.rs index 1b976b7..61c6084 100644 --- a/ctr-std/src/thread/mod.rs +++ b/ctr-std/src/thread/mod.rs @@ -731,7 +731,8 @@ const NOTIFIED: usize = 2; /// specifying a maximum time to block the thread for. /// /// * The [`unpark`] method on a [`Thread`] atomically makes the token available -/// if it wasn't already. +/// if it wasn't already. Because the token is initially absent, [`unpark`] +/// followed by [`park`] will result in the second call returning immediately. /// /// In other words, each [`Thread`] acts a bit like a spinlock that can be /// locked and unlocked using `park` and `unpark`. @@ -766,6 +767,8 @@ const NOTIFIED: usize = 2; /// // Let some time pass for the thread to be spawned. /// thread::sleep(Duration::from_millis(10)); /// +/// // There is no race condition here, if `unpark` +/// // happens first, `park` will return immediately. /// println!("Unpark the thread"); /// parked_thread.thread().unpark(); /// @@ -796,7 +799,10 @@ pub fn park() { let mut m = thread.inner.lock.lock().unwrap(); match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { Ok(_) => {} - Err(NOTIFIED) => return, // notified after we locked + Err(NOTIFIED) => { + thread.inner.state.store(EMPTY, SeqCst); + return; + } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => panic!("inconsistent park state"), } loop { @@ -882,7 +888,10 @@ pub fn park_timeout(dur: Duration) { let m = thread.inner.lock.lock().unwrap(); match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) { Ok(_) => {} - Err(NOTIFIED) => return, // notified after we locked + Err(NOTIFIED) => { + thread.inner.state.store(EMPTY, SeqCst); + return; + } // should consume this notification, so prohibit spurious wakeups in next park. Err(_) => panic!("inconsistent park_timeout state"), } @@ -931,24 +940,23 @@ pub struct ThreadId(u64); impl ThreadId { // Generate a new unique thread ID. fn new() -> ThreadId { + // We never call `GUARD.init()`, so it is UB to attempt to + // acquire this mutex reentrantly! static GUARD: mutex::Mutex = mutex::Mutex::new(); static mut COUNTER: u64 = 0; unsafe { - GUARD.lock(); + let _guard = GUARD.lock(); // If we somehow use up all our bits, panic so that we're not // covering up subtle bugs of IDs being reused. if COUNTER == ::u64::MAX { - GUARD.unlock(); panic!("failed to generate unique thread ID: bitspace exhausted"); } let id = COUNTER; COUNTER += 1; - GUARD.unlock(); - ThreadId(id) } } @@ -1172,7 +1180,7 @@ impl fmt::Debug for Thread { /// /// [`Result`]: ../../std/result/enum.Result.html #[stable(feature = "rust1", since = "1.0.0")] -pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>; +pub type Result<T> = ::result::Result<T, Box<dyn Any + Send + 'static>>; // This packet is used to communicate the return value between the child thread // and the parent thread. Memory is shared through the `Arc` within and there's @@ -1273,6 +1281,11 @@ impl<T> JoinInner<T> { #[stable(feature = "rust1", since = "1.0.0")] pub struct JoinHandle<T>(JoinInner<T>); +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl<T> Send for JoinHandle<T> {} +#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")] +unsafe impl<T> Sync for JoinHandle<T> {} + impl<T> JoinHandle<T> { /// Extracts a handle to the underlying thread. /// @@ -1435,7 +1448,7 @@ mod tests { rx.recv().unwrap(); } - fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<Fn() + Send>) { + fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Box<dyn Fn() + Send>) { let (tx, rx) = channel(); let x: Box<_> = box 1; @@ -1482,7 +1495,7 @@ mod tests { // (well, it would if the constant were 8000+ - I lowered it to be more // valgrind-friendly. try this at home, instead..!) const GENERATIONS: u32 = 16; - fn child_no(x: u32) -> Box<Fn() + Send> { + fn child_no(x: u32) -> Box<dyn Fn() + Send> { return Box::new(move|| { if x < GENERATIONS { thread::spawn(move|| child_no(x+1)()); @@ -1528,10 +1541,10 @@ mod tests { #[test] fn test_try_panic_message_any() { match thread::spawn(move|| { - panic!(box 413u16 as Box<Any + Send>); + panic!(box 413u16 as Box<dyn Any + Send>); }).join() { Err(e) => { - type T = Box<Any + Send>; + type T = Box<dyn Any + Send>; assert!(e.is::<T>()); let any = e.downcast::<T>().unwrap(); assert!(any.is::<u16>()); |