summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys_common
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys_common')
-rw-r--r--library/std/src/sys_common/condvar.rs57
-rw-r--r--library/std/src/sys_common/condvar/check.rs58
-rw-r--r--library/std/src/sys_common/mod.rs4
-rw-r--r--library/std/src/sys_common/mutex.rs50
-rw-r--r--library/std/src/sys_common/once/generic.rs1
-rw-r--r--library/std/src/sys_common/remutex.rs10
-rw-r--r--library/std/src/sys_common/rwlock.rs71
-rw-r--r--library/std/src/sys_common/wstr.rs59
8 files changed, 66 insertions, 244 deletions
diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs
deleted file mode 100644
index 8bc5b2411..000000000
--- a/library/std/src/sys_common/condvar.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use crate::sys::locks as imp;
-use crate::sys_common::mutex::MovableMutex;
-use crate::time::Duration;
-
-mod check;
-
-type CondvarCheck = <imp::MovableMutex as check::CondvarCheck>::Check;
-
-/// An OS-based condition variable.
-pub struct Condvar {
- inner: imp::MovableCondvar,
- check: CondvarCheck,
-}
-
-impl Condvar {
- /// Creates a new condition variable for use.
- #[inline]
- #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
- pub const fn new() -> Self {
- Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() }
- }
-
- /// Signals one waiter on this condition variable to wake up.
- #[inline]
- pub fn notify_one(&self) {
- unsafe { self.inner.notify_one() };
- }
-
- /// Awakens all current waiters on this condition variable.
- #[inline]
- pub fn notify_all(&self) {
- unsafe { self.inner.notify_all() };
- }
-
- /// Waits for a signal on the specified mutex.
- ///
- /// Behavior is undefined if the mutex is not locked by the current thread.
- ///
- /// May panic if used with more than one mutex.
- #[inline]
- pub unsafe fn wait(&self, mutex: &MovableMutex) {
- self.check.verify(mutex);
- self.inner.wait(mutex.raw())
- }
-
- /// Waits for a signal on the specified mutex with a timeout duration
- /// specified by `dur` (a relative time into the future).
- ///
- /// Behavior is undefined if the mutex is not locked by the current thread.
- ///
- /// May panic if used with more than one mutex.
- #[inline]
- pub unsafe fn wait_timeout(&self, mutex: &MovableMutex, dur: Duration) -> bool {
- self.check.verify(mutex);
- self.inner.wait_timeout(mutex.raw(), dur)
- }
-}
diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs
deleted file mode 100644
index 4ac9e62bf..000000000
--- a/library/std/src/sys_common/condvar/check.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-use crate::ptr;
-use crate::sync::atomic::{AtomicPtr, Ordering};
-use crate::sys::locks as imp;
-use crate::sys_common::lazy_box::{LazyBox, LazyInit};
-use crate::sys_common::mutex::MovableMutex;
-
-pub trait CondvarCheck {
- type Check;
-}
-
-/// For boxed mutexes, a `Condvar` will check it's only ever used with the same
-/// mutex, based on its (stable) address.
-impl<T: LazyInit> CondvarCheck for LazyBox<T> {
- type Check = SameMutexCheck;
-}
-
-pub struct SameMutexCheck {
- addr: AtomicPtr<()>,
-}
-
-#[allow(dead_code)]
-impl SameMutexCheck {
- pub const fn new() -> Self {
- Self { addr: AtomicPtr::new(ptr::null_mut()) }
- }
- pub fn verify(&self, mutex: &MovableMutex) {
- let addr = mutex.raw() as *const imp::Mutex as *const () as *mut _;
- // Relaxed is okay here because we never read through `self.addr`, and only use it to
- // compare addresses.
- match self.addr.compare_exchange(
- ptr::null_mut(),
- addr,
- Ordering::Relaxed,
- Ordering::Relaxed,
- ) {
- Ok(_) => {} // Stored the address
- Err(n) if n == addr => {} // Lost a race to store the same address
- _ => panic!("attempted to use a condition variable with two mutexes"),
- }
- }
-}
-
-/// Unboxed mutexes may move, so `Condvar` can not require its address to stay
-/// constant.
-impl CondvarCheck for imp::Mutex {
- type Check = NoCheck;
-}
-
-pub struct NoCheck;
-
-#[allow(dead_code)]
-impl NoCheck {
- #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
- pub const fn new() -> Self {
- Self
- }
- pub fn verify(&self, _: &MovableMutex) {}
-}
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 8c19f9332..b1987aa0f 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -21,20 +21,18 @@
mod tests;
pub mod backtrace;
-pub mod condvar;
pub mod fs;
pub mod io;
pub mod lazy_box;
pub mod memchr;
-pub mod mutex;
pub mod once;
pub mod process;
pub mod remutex;
-pub mod rwlock;
pub mod thread;
pub mod thread_info;
pub mod thread_local_dtor;
pub mod thread_parker;
+pub mod wstr;
pub mod wtf8;
cfg_if::cfg_if! {
diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs
deleted file mode 100644
index 98046f20f..000000000
--- a/library/std/src/sys_common/mutex.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use crate::sys::locks as imp;
-
-/// An OS-based mutual exclusion lock.
-///
-/// This mutex cleans up its resources in its `Drop` implementation, may safely
-/// be moved (when not borrowed), and does not cause UB when used reentrantly.
-///
-/// This mutex does not implement poisoning.
-///
-/// This is either a wrapper around `LazyBox<imp::Mutex>` or `imp::Mutex`,
-/// depending on the platform. It is boxed on platforms where `imp::Mutex` may
-/// not be moved.
-pub struct MovableMutex(imp::MovableMutex);
-
-unsafe impl Sync for MovableMutex {}
-
-impl MovableMutex {
- /// Creates a new mutex.
- #[inline]
- #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
- pub const fn new() -> Self {
- Self(imp::MovableMutex::new())
- }
-
- pub(super) fn raw(&self) -> &imp::Mutex {
- &self.0
- }
-
- /// Locks the mutex blocking the current thread until it is available.
- #[inline]
- pub fn raw_lock(&self) {
- unsafe { self.0.lock() }
- }
-
- /// Attempts to lock the mutex without blocking, returning whether it was
- /// successfully acquired or not.
- #[inline]
- pub fn try_lock(&self) -> bool {
- unsafe { self.0.try_lock() }
- }
-
- /// Unlocks the mutex.
- ///
- /// Behavior is undefined if the current thread does not actually hold the
- /// mutex.
- #[inline]
- pub unsafe fn raw_unlock(&self) {
- self.0.unlock()
- }
-}
diff --git a/library/std/src/sys_common/once/generic.rs b/library/std/src/sys_common/once/generic.rs
index acf5f2471..d953a6745 100644
--- a/library/std/src/sys_common/once/generic.rs
+++ b/library/std/src/sys_common/once/generic.rs
@@ -107,6 +107,7 @@ struct WaiterQueue<'a> {
impl Once {
#[inline]
+ #[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
pub const fn new() -> Once {
Once { state_and_queue: AtomicPtr::new(ptr::invalid_mut(INCOMPLETE)) }
}
diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sys_common/remutex.rs
index b448ae3a9..4c054da64 100644
--- a/library/std/src/sys_common/remutex.rs
+++ b/library/std/src/sys_common/remutex.rs
@@ -1,11 +1,11 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use super::mutex as sys;
use crate::cell::UnsafeCell;
use crate::ops::Deref;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+use crate::sys::locks as sys;
/// A re-entrant mutual exclusion
///
@@ -39,7 +39,7 @@ use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
/// synchronization is left to the mutex, making relaxed memory ordering for
/// the `owner` field fine in all cases.
pub struct ReentrantMutex<T> {
- mutex: sys::MovableMutex,
+ mutex: sys::Mutex,
owner: AtomicUsize,
lock_count: UnsafeCell<u32>,
data: T,
@@ -74,7 +74,7 @@ impl<T> ReentrantMutex<T> {
/// Creates a new reentrant mutex in an unlocked state.
pub const fn new(t: T) -> ReentrantMutex<T> {
ReentrantMutex {
- mutex: sys::MovableMutex::new(),
+ mutex: sys::Mutex::new(),
owner: AtomicUsize::new(0),
lock_count: UnsafeCell::new(0),
data: t,
@@ -100,7 +100,7 @@ impl<T> ReentrantMutex<T> {
if self.owner.load(Relaxed) == this_thread {
self.increment_lock_count();
} else {
- self.mutex.raw_lock();
+ self.mutex.lock();
self.owner.store(this_thread, Relaxed);
debug_assert_eq!(*self.lock_count.get(), 0);
*self.lock_count.get() = 1;
@@ -162,7 +162,7 @@ impl<T> Drop for ReentrantMutexGuard<'_, T> {
*self.lock.lock_count.get() -= 1;
if *self.lock.lock_count.get() == 0 {
self.lock.owner.store(0, Relaxed);
- self.lock.mutex.raw_unlock();
+ self.lock.mutex.unlock();
}
}
}
diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs
deleted file mode 100644
index 042981dac..000000000
--- a/library/std/src/sys_common/rwlock.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-use crate::sys::locks as imp;
-
-/// An OS-based reader-writer lock.
-///
-/// This rwlock cleans up its resources in its `Drop` implementation and may
-/// safely be moved (when not borrowed).
-///
-/// This rwlock does not implement poisoning.
-///
-/// This is either a wrapper around `LazyBox<imp::RwLock>` or `imp::RwLock`,
-/// depending on the platform. It is boxed on platforms where `imp::RwLock` may
-/// not be moved.
-pub struct MovableRwLock(imp::MovableRwLock);
-
-impl MovableRwLock {
- /// Creates a new reader-writer lock for use.
- #[inline]
- #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
- pub const fn new() -> Self {
- Self(imp::MovableRwLock::new())
- }
-
- /// Acquires shared access to the underlying lock, blocking the current
- /// thread to do so.
- #[inline]
- pub fn read(&self) {
- unsafe { self.0.read() }
- }
-
- /// Attempts to acquire shared access to this lock, returning whether it
- /// succeeded or not.
- ///
- /// This function does not block the current thread.
- #[inline]
- pub fn try_read(&self) -> bool {
- unsafe { self.0.try_read() }
- }
-
- /// Acquires write access to the underlying lock, blocking the current thread
- /// to do so.
- #[inline]
- pub fn write(&self) {
- unsafe { self.0.write() }
- }
-
- /// Attempts to acquire exclusive access to this lock, returning whether it
- /// succeeded or not.
- ///
- /// This function does not block the current thread.
- #[inline]
- pub fn try_write(&self) -> bool {
- unsafe { self.0.try_write() }
- }
-
- /// Unlocks previously acquired shared access to this lock.
- ///
- /// Behavior is undefined if the current thread does not have shared access.
- #[inline]
- pub unsafe fn read_unlock(&self) {
- self.0.read_unlock()
- }
-
- /// Unlocks previously acquired exclusive access to this lock.
- ///
- /// Behavior is undefined if the current thread does not currently have
- /// exclusive access.
- #[inline]
- pub unsafe fn write_unlock(&self) {
- self.0.write_unlock()
- }
-}
diff --git a/library/std/src/sys_common/wstr.rs b/library/std/src/sys_common/wstr.rs
new file mode 100644
index 000000000..b230fd1a8
--- /dev/null
+++ b/library/std/src/sys_common/wstr.rs
@@ -0,0 +1,59 @@
+//! This module contains constructs to work with 16-bit characters (UCS-2 or UTF-16)
+#![allow(dead_code)]
+
+use crate::marker::PhantomData;
+use crate::num::NonZeroU16;
+use crate::ptr::NonNull;
+
+/// A safe iterator over a LPWSTR
+/// (aka a pointer to a series of UTF-16 code units terminated by a NULL).
+pub struct WStrUnits<'a> {
+ // The pointer must never be null...
+ lpwstr: NonNull<u16>,
+ // ...and the memory it points to must be valid for this lifetime.
+ lifetime: PhantomData<&'a [u16]>,
+}
+
+impl WStrUnits<'_> {
+ /// Create the iterator. Returns `None` if `lpwstr` is null.
+ ///
+ /// SAFETY: `lpwstr` must point to a null-terminated wide string that lives
+ /// at least as long as the lifetime of this struct.
+ pub unsafe fn new(lpwstr: *const u16) -> Option<Self> {
+ Some(Self { lpwstr: NonNull::new(lpwstr as _)?, lifetime: PhantomData })
+ }
+
+ pub fn peek(&self) -> Option<NonZeroU16> {
+ // SAFETY: It's always safe to read the current item because we don't
+ // ever move out of the array's bounds.
+ unsafe { NonZeroU16::new(*self.lpwstr.as_ptr()) }
+ }
+
+ /// Advance the iterator while `predicate` returns true.
+ /// Returns the number of items it advanced by.
+ pub fn advance_while<P: FnMut(NonZeroU16) -> bool>(&mut self, mut predicate: P) -> usize {
+ let mut counter = 0;
+ while let Some(w) = self.peek() {
+ if !predicate(w) {
+ break;
+ }
+ counter += 1;
+ self.next();
+ }
+ counter
+ }
+}
+
+impl Iterator for WStrUnits<'_> {
+ // This can never return zero as that marks the end of the string.
+ type Item = NonZeroU16;
+ fn next(&mut self) -> Option<NonZeroU16> {
+ // SAFETY: If NULL is reached we immediately return.
+ // Therefore it's safe to advance the pointer after that.
+ unsafe {
+ let next = self.peek()?;
+ self.lpwstr = NonNull::new_unchecked(self.lpwstr.as_ptr().add(1));
+ Some(next)
+ }
+ }
+}