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.
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() };
}
}