]> git.lizzy.rs Git - rust.git/blobdiff - library/std/src/sys_common/rwlock.rs
Merge `sys_common::bytestring` into `os_str_bytes`
[rust.git] / library / std / src / sys_common / rwlock.rs
index 3705d641a1be646ab38436b8aaed032a6ef3e312..07ec20f4dc6177fa0c4642ac9e96bab00d9affd7 100644 (file)
 use crate::sys::rwlock as imp;
 
+/// An OS-based reader-writer lock, meant for use in static variables.
+///
+/// This rwlock does not implement poisoning.
+///
+/// This rwlock has a const constructor ([`StaticRWLock::new`]), does not
+/// implement `Drop` to cleanup resources.
+pub struct StaticRWLock(imp::RWLock);
+
+impl StaticRWLock {
+    /// Creates a new rwlock for use.
+    pub const fn new() -> Self {
+        Self(imp::RWLock::new())
+    }
+
+    /// Acquires shared access to the underlying lock, blocking the current
+    /// thread to do so.
+    ///
+    /// The lock is automatically unlocked when the returned guard is dropped.
+    #[inline]
+    pub fn read(&'static self) -> StaticRWLockReadGuard {
+        unsafe { self.0.read() };
+        StaticRWLockReadGuard(&self.0)
+    }
+
+    /// Acquires write access to the underlying lock, blocking the current thread
+    /// to do so.
+    ///
+    /// The lock is automatically unlocked when the returned guard is dropped.
+    #[inline]
+    pub fn write(&'static self) -> StaticRWLockWriteGuard {
+        unsafe { self.0.write() };
+        StaticRWLockWriteGuard(&self.0)
+    }
+}
+
+#[must_use]
+pub struct StaticRWLockReadGuard(&'static imp::RWLock);
+
+impl Drop for StaticRWLockReadGuard {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe {
+            self.0.read_unlock();
+        }
+    }
+}
+
+#[must_use]
+pub struct StaticRWLockWriteGuard(&'static imp::RWLock);
+
+impl Drop for StaticRWLockWriteGuard {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe {
+            self.0.write_unlock();
+        }
+    }
+}
+
 /// An OS-based reader-writer lock.
 ///
-/// This structure is entirely unsafe and serves as the lowest layer of a
-/// cross-platform binding of system rwlocks. It is recommended to use the
-/// safer types at the top level of this crate instead of this type.
-pub struct RWLock(imp::RWLock);
+/// This rwlock does *not* have a const constructor, 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 `Box<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 RWLock {
+impl MovableRWLock {
     /// Creates a new reader-writer lock for use.
-    ///
-    /// Behavior is undefined if the reader-writer lock is moved after it is
-    /// first used with any of the functions below.
-    pub const fn new() -> RWLock {
-        RWLock(imp::RWLock::new())
+    pub fn new() -> Self {
+        Self(imp::MovableRWLock::from(imp::RWLock::new()))
     }
 
     /// Acquires shared access to the underlying lock, blocking the current
     /// thread to do so.
-    ///
-    /// Behavior is undefined if the rwlock has been moved between this and any
-    /// previous method call.
     #[inline]
-    pub unsafe fn read(&self) {
-        self.0.read()
+    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.
-    ///
-    /// Behavior is undefined if the rwlock has been moved between this and any
-    /// previous method call.
     #[inline]
-    pub unsafe fn try_read(&self) -> bool {
-        self.0.try_read()
+    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.
-    ///
-    /// Behavior is undefined if the rwlock has been moved between this and any
-    /// previous method call.
     #[inline]
-    pub unsafe fn write(&self) {
-        self.0.write()
+    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.
-    ///
-    /// Behavior is undefined if the rwlock has been moved between this and any
-    /// previous method call.
     #[inline]
-    pub unsafe fn try_write(&self) -> bool {
-        self.0.try_write()
+    pub fn try_write(&self) -> bool {
+        unsafe { self.0.try_write() }
     }
 
     /// Unlocks previously acquired shared access to this lock.
@@ -76,13 +125,10 @@ pub unsafe fn read_unlock(&self) {
     pub unsafe fn write_unlock(&self) {
         self.0.write_unlock()
     }
+}
 
-    /// Destroys OS-related resources with this RWLock.
-    ///
-    /// Behavior is undefined if there are any currently active users of this
-    /// lock.
-    #[inline]
-    pub unsafe fn destroy(&self) {
-        self.0.destroy()
+impl Drop for MovableRWLock {
+    fn drop(&mut self) {
+        unsafe { self.0.destroy() };
     }
 }