diff options
| author | joboet <jonasboettiger@icloud.com> | 2022-04-25 15:19:50 +0200 |
|---|---|---|
| committer | joboet <jonasboettiger@icloud.com> | 2022-04-25 15:19:50 +0200 |
| commit | 54daf496e2e957a9f69aa88bf6c42520a2dbfa02 (patch) | |
| tree | 3ecee0dc5e3b5f0e8c3a93ce4bd6ecb5eaf05a5f /library/std/src/thread | |
| parent | b759b2218649016cc40e82bdd6d958e2277ff6d7 (diff) | |
| download | rust-54daf496e2e957a9f69aa88bf6c42520a2dbfa02.tar.gz rust-54daf496e2e957a9f69aa88bf6c42520a2dbfa02.zip | |
std: directly use pthread in UNIX parker implementation
Mutex and Condvar are being replaced by more efficient implementations, which need thread parking themselves (see #93740). Therefore use the pthread synchronization primitives directly. Also, avoid allocating because the Parker struct is being placed in an Arc anyways.
Diffstat (limited to 'library/std/src/thread')
| -rw-r--r-- | library/std/src/thread/mod.rs | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 5309dc47ac4..99da5f7a87e 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -163,6 +163,8 @@ use crate::num::NonZeroU64; use crate::num::NonZeroUsize; use crate::panic; use crate::panicking; +use crate::pin::Pin; +use crate::ptr::addr_of_mut; use crate::str; use crate::sync::Arc; use crate::sys::thread as imp; @@ -923,7 +925,7 @@ pub fn sleep(dur: Duration) { pub fn park() { // SAFETY: park_timeout is called on the parker owned by this thread. unsafe { - current().inner.parker.park(); + current().inner.as_ref().parker().park(); } } @@ -987,7 +989,7 @@ pub fn park_timeout_ms(ms: u32) { pub fn park_timeout(dur: Duration) { // SAFETY: park_timeout is called on the parker owned by this thread. unsafe { - current().inner.parker.park_timeout(dur); + current().inner.as_ref().parker().park_timeout(dur); } } @@ -1073,6 +1075,12 @@ struct Inner { parker: Parker, } +impl Inner { + fn parker(self: Pin<&Self>) -> Pin<&Parker> { + unsafe { Pin::map_unchecked(self, |inner| &inner.parker) } + } +} + #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] /// A handle to a thread. @@ -1094,14 +1102,28 @@ struct Inner { /// /// [`thread::current`]: current pub struct Thread { - inner: Arc<Inner>, + inner: Pin<Arc<Inner>>, } impl Thread { // Used only internally to construct a thread object without spawning // Panics if the name contains nuls. pub(crate) fn new(name: Option<CString>) -> Thread { - Thread { inner: Arc::new(Inner { name, id: ThreadId::new(), parker: Parker::new() }) } + // We have to use `unsafe` here to constuct the `Parker` in-place, + // which is required for the UNIX implementation. + // + // SAFETY: We pin the Arc immediately after creation, so its address never + // changes. + let inner = unsafe { + let mut arc = Arc::<Inner>::new_uninit(); + let ptr = Arc::get_mut_unchecked(&mut arc).as_mut_ptr(); + addr_of_mut!((*ptr).name).write(name); + addr_of_mut!((*ptr).id).write(ThreadId::new()); + Parker::new(addr_of_mut!((*ptr).parker)); + Pin::new_unchecked(arc.assume_init()) + }; + + Thread { inner } } /// Atomically makes the handle's token available if it is not already. @@ -1137,7 +1159,7 @@ impl Thread { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn unpark(&self) { - self.inner.parker.unpark(); + self.inner.as_ref().parker().unpark(); } /// Gets the thread's unique identifier. |
