diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /vendor/fd-lock/src | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/fd-lock/src')
-rw-r--r-- | vendor/fd-lock/src/lib.rs | 43 | ||||
-rw-r--r-- | vendor/fd-lock/src/read_guard.rs | 43 | ||||
-rw-r--r-- | vendor/fd-lock/src/rw_lock.rs | 126 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/mod.rs | 17 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unix/mod.rs | 7 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unix/read_guard.rs | 32 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unix/rw_lock.rs | 70 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unix/write_guard.rs | 39 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unsupported/mod.rs | 9 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unsupported/read_guard.rs | 31 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unsupported/rw_lock.rs | 44 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unsupported/utils.rs | 9 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/unsupported/write_guard.rs | 38 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/windows/mod.rs | 8 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/windows/read_guard.rs | 31 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/windows/rw_lock.rs | 72 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/windows/utils.rs | 33 | ||||
-rw-r--r-- | vendor/fd-lock/src/sys/windows/write_guard.rs | 38 | ||||
-rw-r--r-- | vendor/fd-lock/src/write_guard.rs | 50 |
19 files changed, 740 insertions, 0 deletions
diff --git a/vendor/fd-lock/src/lib.rs b/vendor/fd-lock/src/lib.rs new file mode 100644 index 000000000..9d3d6192b --- /dev/null +++ b/vendor/fd-lock/src/lib.rs @@ -0,0 +1,43 @@ +//! Advisory reader-writer locks for files. +//! +//! # Notes on Advisory Locks +//! +//! "advisory locks" are locks which programs must opt-in to adhere to. This +//! means that they can be used to coordinate file access, but not prevent +//! access. Use this to coordinate file access between multiple instances of the +//! same program. But do not use this to prevent actors from accessing or +//! modifying files. +//! +//! # Example +//! +//! ```no_run +//! # use std::io; +//! use std::io::prelude::*; +//! use std::fs::File; +//! use fd_lock::RwLock; +//! +//! # fn main() -> io::Result<()> { +//! // Lock a file and write to it. +//! let mut f = RwLock::new(File::open("foo.txt")?); +//! write!(f.write()?, "chashu cat")?; +//! +//! // A lock can also be held across multiple operations. +//! let mut f = f.write()?; +//! write!(f, "nori cat")?; +//! write!(f, "bird!")?; +//! # Ok(()) } +//! ``` + +#![forbid(future_incompatible)] +#![deny(missing_debug_implementations, nonstandard_style)] +#![cfg_attr(doc, warn(missing_docs, rustdoc::missing_doc_code_examples))] + +mod read_guard; +mod rw_lock; +mod write_guard; + +pub(crate) mod sys; + +pub use read_guard::RwLockReadGuard; +pub use rw_lock::RwLock; +pub use write_guard::RwLockWriteGuard; diff --git a/vendor/fd-lock/src/read_guard.rs b/vendor/fd-lock/src/read_guard.rs new file mode 100644 index 000000000..29ed06da3 --- /dev/null +++ b/vendor/fd-lock/src/read_guard.rs @@ -0,0 +1,43 @@ +use std::ops; + +use crate::sys; + +/// RAII structure used to release the shared read access of a lock when +/// dropped. +/// +/// This structure is created by the [`read`] and [`try_read`] methods on +/// [`RwLock`]. +/// +/// [`read`]: crate::RwLock::read +/// [`try_read`]: crate::RwLock::try_read +/// [`RwLock`]: crate::RwLock +/// +/// # Panics +/// +/// Dropping this type may panic if the lock fails to unlock. +#[must_use = "if unused the RwLock will immediately unlock"] +#[derive(Debug)] +pub struct RwLockReadGuard<'lock, T: sys::AsRaw> { + guard: sys::RwLockReadGuard<'lock, T>, +} + +impl<'lock, T: sys::AsRaw> RwLockReadGuard<'lock, T> { + pub(crate) fn new(guard: sys::RwLockReadGuard<'lock, T>) -> Self { + Self { guard } + } +} + +impl<T: sys::AsRaw> ops::Deref for RwLockReadGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + self.guard.deref() + } +} + +/// Release the lock. +impl<T: sys::AsRaw> Drop for RwLockReadGuard<'_, T> { + #[inline] + fn drop(&mut self) {} +} diff --git a/vendor/fd-lock/src/rw_lock.rs b/vendor/fd-lock/src/rw_lock.rs new file mode 100644 index 000000000..77f9d2231 --- /dev/null +++ b/vendor/fd-lock/src/rw_lock.rs @@ -0,0 +1,126 @@ +use crate::read_guard::RwLockReadGuard; +use crate::sys; +use crate::write_guard::RwLockWriteGuard; +use std::io; + +/// Advisory reader-writer lock for files. +/// +/// This type of lock allows a number of readers or at most one writer at any point +/// in time. The write portion of this lock typically allows modification of the +/// underlying data (exclusive access) and the read portion of this lock typically +/// allows for read-only access (shared access). +#[derive(Debug)] +pub struct RwLock<T: sys::AsRaw> { + lock: sys::RwLock<T>, +} + +impl<T: sys::AsRaw> RwLock<T> { + /// Create a new instance. + /// + /// # Examples + /// + /// ```no_run + /// use fd_lock::RwLock; + /// use std::fs::File; + /// + /// fn main() -> std::io::Result<()> { + /// let mut f = RwLock::new(File::open("foo.txt")?); + /// Ok(()) + /// } + /// ``` + #[inline] + pub fn new(inner: T) -> Self { + Self { + lock: sys::RwLock::new(inner), + } + } + + /// Locks this lock with shared read access, blocking the current thread + /// until it can be acquired. + /// + /// The calling thread will be blocked until there are no more writers which + /// hold the lock. There may be other readers currently inside the lock when + /// this method returns. This method does not provide any guarantees with + /// respect to the ordering of whether contentious readers or writers will + /// acquire the lock first. + /// + /// Returns an RAII guard which will release this thread's shared access + /// once it is dropped. + /// + /// # Errors + /// + /// On Unix this may return an `ErrorKind::Interrupted` if the operation was + /// interrupted by a signal handler. + #[inline] + pub fn read(&self) -> io::Result<RwLockReadGuard<'_, T>> { + let guard = self.lock.read()?; + Ok(RwLockReadGuard::new(guard)) + } + + /// Attempts to acquire this lock with shared read access. + /// + /// If the access could not be granted at this time, then `Err` is returned. + /// Otherwise, an RAII guard is returned which will release the shared access + /// when it is dropped. + /// + /// This function does not block. + /// + /// This function does not provide any guarantees with respect to the ordering + /// of whether contentious readers or writers will acquire the lock first. + /// + /// # Errors + /// + /// If the lock is already held and `ErrorKind::WouldBlock` error is returned. + /// On Unix this may return an `ErrorKind::Interrupted` if the operation was + /// interrupted by a signal handler. + #[inline] + pub fn try_read(&self) -> io::Result<RwLockReadGuard<'_, T>> { + let guard = self.lock.try_read()?; + Ok(RwLockReadGuard::new(guard)) + } + + /// Locks this lock with exclusive write access, blocking the current thread + /// until it can be acquired. + /// + /// This function will not return while other writers or other readers + /// currently have access to the lock. + /// + /// Returns an RAII guard which will drop the write access of this rwlock + /// when dropped. + /// + /// # Errors + /// + /// On Unix this may return an `ErrorKind::Interrupted` if the operation was + /// interrupted by a signal handler. + #[inline] + pub fn write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> { + let guard = self.lock.write()?; + Ok(RwLockWriteGuard::new(guard)) + } + + /// Attempts to lock this lock with exclusive write access. + /// + /// If the lock could not be acquired at this time, then `Err` is returned. + /// Otherwise, an RAII guard is returned which will release the lock when + /// it is dropped. + /// + /// # Errors + /// + /// If the lock is already held and `ErrorKind::WouldBlock` error is returned. + /// On Unix this may return an `ErrorKind::Interrupted` if the operation was + /// interrupted by a signal handler. + #[inline] + pub fn try_write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> { + let guard = self.lock.try_write()?; + Ok(RwLockWriteGuard::new(guard)) + } + + /// Consumes this `RwLock`, returning the underlying data. + #[inline] + pub fn into_inner(self) -> T + where + T: Sized, + { + self.lock.into_inner() + } +} diff --git a/vendor/fd-lock/src/sys/mod.rs b/vendor/fd-lock/src/sys/mod.rs new file mode 100644 index 000000000..3c6391e98 --- /dev/null +++ b/vendor/fd-lock/src/sys/mod.rs @@ -0,0 +1,17 @@ +use cfg_if::cfg_if; + +cfg_if! { + if #[cfg(unix)] { + mod unix; + pub use unix::*; + pub(crate) use std::os::unix::prelude::AsRawFd as AsRaw; + } else if #[cfg(windows)] { + mod windows; + pub use windows::*; + #[doc(no_inline)] + pub(crate) use std::os::windows::prelude::AsRawHandle as AsRaw; + } else { + mod unsupported; + pub use unsupported; + } +} diff --git a/vendor/fd-lock/src/sys/unix/mod.rs b/vendor/fd-lock/src/sys/unix/mod.rs new file mode 100644 index 000000000..023e69187 --- /dev/null +++ b/vendor/fd-lock/src/sys/unix/mod.rs @@ -0,0 +1,7 @@ +mod read_guard; +mod rw_lock; +mod write_guard; + +pub use read_guard::RwLockReadGuard; +pub use rw_lock::RwLock; +pub use write_guard::RwLockWriteGuard; diff --git a/vendor/fd-lock/src/sys/unix/read_guard.rs b/vendor/fd-lock/src/sys/unix/read_guard.rs new file mode 100644 index 000000000..6d6718789 --- /dev/null +++ b/vendor/fd-lock/src/sys/unix/read_guard.rs @@ -0,0 +1,32 @@ +use rustix::fs::{flock, FlockOperation}; +use std::ops; +use std::os::unix::io::AsRawFd; + +use super::RwLock; + +#[derive(Debug)] +pub struct RwLockReadGuard<'lock, T: AsRawFd> { + lock: &'lock RwLock<T>, +} + +impl<'lock, T: AsRawFd> RwLockReadGuard<'lock, T> { + pub(crate) fn new(lock: &'lock RwLock<T>) -> Self { + Self { lock } + } +} + +impl<T: AsRawFd> ops::Deref for RwLockReadGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.lock.inner + } +} + +impl<T: AsRawFd> Drop for RwLockReadGuard<'_, T> { + #[inline] + fn drop(&mut self) { + let _ = flock(&self.lock.as_fd(), FlockOperation::Unlock).ok(); + } +} diff --git a/vendor/fd-lock/src/sys/unix/rw_lock.rs b/vendor/fd-lock/src/sys/unix/rw_lock.rs new file mode 100644 index 000000000..c33ce5c78 --- /dev/null +++ b/vendor/fd-lock/src/sys/unix/rw_lock.rs @@ -0,0 +1,70 @@ +use rustix::fd::BorrowedFd; +use rustix::fs::{flock, FlockOperation}; +use std::io::{self, Error, ErrorKind}; +use std::os::unix::io::AsRawFd; + +use super::{RwLockReadGuard, RwLockWriteGuard}; + +#[derive(Debug)] +pub struct RwLock<T: AsRawFd> { + pub(crate) inner: T, +} + +impl<T: AsRawFd> RwLock<T> { + #[inline] + pub fn new(inner: T) -> Self { + RwLock { inner } + } + + #[inline] + pub fn write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> { + flock(&self.as_fd(), FlockOperation::LockExclusive)?; + Ok(RwLockWriteGuard::new(self)) + } + + #[inline] + pub fn try_write(&mut self) -> Result<RwLockWriteGuard<'_, T>, Error> { + flock(&self.as_fd(), FlockOperation::NonBlockingLockExclusive).map_err(|err| match err + .kind() + { + ErrorKind::AlreadyExists => ErrorKind::WouldBlock.into(), + _ => Error::from(err), + })?; + Ok(RwLockWriteGuard::new(self)) + } + + #[inline] + pub fn read(&self) -> io::Result<RwLockReadGuard<'_, T>> { + flock(&self.as_fd(), FlockOperation::LockShared)?; + Ok(RwLockReadGuard::new(self)) + } + + #[inline] + pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, Error> { + flock(&self.as_fd(), FlockOperation::NonBlockingLockShared).map_err(|err| { + match err.kind() { + ErrorKind::AlreadyExists => ErrorKind::WouldBlock.into(), + _ => Error::from(err), + } + })?; + Ok(RwLockReadGuard::new(self)) + } + + #[inline] + pub fn into_inner(self) -> T + where + T: Sized, + { + self.inner + } + + #[inline] + pub(crate) fn as_fd(&self) -> BorrowedFd<'_> { + // Safety: We assume that `self.inner`'s file descriptor is valid for + // at least the lifetime of `self`. + // + // Once I/O safety is stablized in std, we can switch the public API to + // use `AsFd` instead of `AsRawFd` and eliminate this `unsafe` block. + unsafe { BorrowedFd::borrow_raw(self.inner.as_raw_fd()) } + } +} diff --git a/vendor/fd-lock/src/sys/unix/write_guard.rs b/vendor/fd-lock/src/sys/unix/write_guard.rs new file mode 100644 index 000000000..a12bdf97a --- /dev/null +++ b/vendor/fd-lock/src/sys/unix/write_guard.rs @@ -0,0 +1,39 @@ +use rustix::fs::{flock, FlockOperation}; +use std::ops; +use std::os::unix::io::AsRawFd; + +use super::RwLock; + +#[derive(Debug)] +pub struct RwLockWriteGuard<'lock, T: AsRawFd> { + lock: &'lock mut RwLock<T>, +} + +impl<'lock, T: AsRawFd> RwLockWriteGuard<'lock, T> { + pub(crate) fn new(lock: &'lock mut RwLock<T>) -> Self { + Self { lock } + } +} + +impl<T: AsRawFd> ops::Deref for RwLockWriteGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.lock.inner + } +} + +impl<T: AsRawFd> ops::DerefMut for RwLockWriteGuard<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.lock.inner + } +} + +impl<T: AsRawFd> Drop for RwLockWriteGuard<'_, T> { + #[inline] + fn drop(&mut self) { + let _ = flock(&self.lock.as_fd(), FlockOperation::Unlock).ok(); + } +} diff --git a/vendor/fd-lock/src/sys/unsupported/mod.rs b/vendor/fd-lock/src/sys/unsupported/mod.rs new file mode 100644 index 000000000..9d7bd2cbd --- /dev/null +++ b/vendor/fd-lock/src/sys/unsupported/mod.rs @@ -0,0 +1,9 @@ +mod read_guard; +mod rw_lock; +mod write_guard; + +pub(crate) mod utils; + +pub use read_guard::RwLockReadGuard; +pub use rw_lock::RwLock; +pub use write_guard::RwLockWriteGuard; diff --git a/vendor/fd-lock/src/sys/unsupported/read_guard.rs b/vendor/fd-lock/src/sys/unsupported/read_guard.rs new file mode 100644 index 000000000..7d6b4c783 --- /dev/null +++ b/vendor/fd-lock/src/sys/unsupported/read_guard.rs @@ -0,0 +1,31 @@ +use std::ops; +use std::os::unix::io::AsRawFd; + +use super::RwLock; + +#[derive(Debug)] +pub struct RwLockReadGuard<'lock, T: AsRawFd> { + lock: &'lock RwLock<T>, +} + +impl<'lock, T: AsRawFd> RwLockReadGuard<'lock, T> { + pub(crate) fn new(lock: &'lock RwLock<T>) -> Self { + panic!("target unsupported") + } +} + +impl<T: AsRawFd> ops::Deref for RwLockReadGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + panic!("target unsupported") + } +} + +impl<T: AsRawFd> Drop for RwLockReadGuard<'_, T> { + #[inline] + fn drop(&mut self) { + panic!("target unsupported") + } +} diff --git a/vendor/fd-lock/src/sys/unsupported/rw_lock.rs b/vendor/fd-lock/src/sys/unsupported/rw_lock.rs new file mode 100644 index 000000000..fb11da84b --- /dev/null +++ b/vendor/fd-lock/src/sys/unsupported/rw_lock.rs @@ -0,0 +1,44 @@ +use std::io::{self, Error, ErrorKind}; +use std::os::unix::io::AsRawFd; + +use super::{RwLockReadGuard, RwLockWriteGuard}; + +#[derive(Debug)] +pub struct RwLock<T: AsRawFd> { + pub(crate) inner: T, +} + +impl<T: AsRawFd> RwLock<T> { + #[inline] + pub fn new(inner: T) -> Self { + panic!("target unsupported") + } + + #[inline] + pub fn write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> { + panic!("target unsupported") + } + + #[inline] + pub fn try_write(&mut self) -> Result<RwLockWriteGuard<'_, T>, Error> { + panic!("target unsupported") + } + + #[inline] + pub fn read(&self) -> io::Result<RwLockReadGuard<'_, T>> { + panic!("target unsupported") + } + + #[inline] + pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, Error> { + panic!("target unsupported") + } + + #[inline] + pub fn into_inner(self) -> T + where + T: Sized, + { + panic!("target unsupported") + } +} diff --git a/vendor/fd-lock/src/sys/unsupported/utils.rs b/vendor/fd-lock/src/sys/unsupported/utils.rs new file mode 100644 index 000000000..191dd0c5c --- /dev/null +++ b/vendor/fd-lock/src/sys/unsupported/utils.rs @@ -0,0 +1,9 @@ +use std::io; +use std::os::raw::c_int; + +pub(crate) fn syscall(int: c_int) -> io::Result<()> { + match int { + 0 => Ok(()), + _ => Err(io::Error::last_os_error()), + } +} diff --git a/vendor/fd-lock/src/sys/unsupported/write_guard.rs b/vendor/fd-lock/src/sys/unsupported/write_guard.rs new file mode 100644 index 000000000..19727c307 --- /dev/null +++ b/vendor/fd-lock/src/sys/unsupported/write_guard.rs @@ -0,0 +1,38 @@ +use std::ops; +use std::os::unix::io::AsRawFd; + +use super::RwLock; + +#[derive(Debug)] +pub struct RwLockWriteGuard<'lock, T: AsRawFd> { + lock: &'lock mut RwLock<T>, +} + +impl<'lock, T: AsRawFd> RwLockWriteGuard<'lock, T> { + pub(crate) fn new(lock: &'lock mut RwLock<T>) -> Self { + panic!("target unsupported") + } +} + +impl<T: AsRawFd> ops::Deref for RwLockWriteGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + panic!("target unsupported") + } +} + +impl<T: AsRawFd> ops::DerefMut for RwLockWriteGuard<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + panic!("target unsupported") + } +} + +impl<T: AsRawFd> Drop for RwLockWriteGuard<'_, T> { + #[inline] + fn drop(&mut self) { + panic!("target unsupported") + } +} diff --git a/vendor/fd-lock/src/sys/windows/mod.rs b/vendor/fd-lock/src/sys/windows/mod.rs new file mode 100644 index 000000000..dafbd31ad --- /dev/null +++ b/vendor/fd-lock/src/sys/windows/mod.rs @@ -0,0 +1,8 @@ +mod read_guard; +mod rw_lock; +mod utils; +mod write_guard; + +pub use read_guard::RwLockReadGuard; +pub use rw_lock::RwLock; +pub use write_guard::RwLockWriteGuard; diff --git a/vendor/fd-lock/src/sys/windows/read_guard.rs b/vendor/fd-lock/src/sys/windows/read_guard.rs new file mode 100644 index 000000000..28f09bb95 --- /dev/null +++ b/vendor/fd-lock/src/sys/windows/read_guard.rs @@ -0,0 +1,31 @@ +use windows_sys::Win32::Foundation::HANDLE; +use windows_sys::Win32::Storage::FileSystem::UnlockFile; + +use std::ops; +use std::os::windows::prelude::*; + +use super::utils::syscall; +use super::RwLock; + +#[derive(Debug)] +pub struct RwLockReadGuard<'lock, T: AsRawHandle> { + pub(crate) lock: &'lock RwLock<T>, +} + +impl<T: AsRawHandle> ops::Deref for RwLockReadGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.lock.inner + } +} + +impl<T: AsRawHandle> Drop for RwLockReadGuard<'_, T> { + #[inline] + fn drop(&mut self) { + let handle = self.lock.inner.as_raw_handle() as HANDLE; + syscall(unsafe { UnlockFile(handle, 0, 0, 1, 0) }) + .expect("Could not unlock the file descriptor"); + } +} diff --git a/vendor/fd-lock/src/sys/windows/rw_lock.rs b/vendor/fd-lock/src/sys/windows/rw_lock.rs new file mode 100644 index 000000000..778b79100 --- /dev/null +++ b/vendor/fd-lock/src/sys/windows/rw_lock.rs @@ -0,0 +1,72 @@ +use std::io::{self, Error, ErrorKind}; +use std::os::windows::io::AsRawHandle; + +use windows_sys::Win32::Foundation::HANDLE; +use windows_sys::Win32::Storage::FileSystem::{ + LockFileEx, LOCKFILE_EXCLUSIVE_LOCK, LOCKFILE_FAIL_IMMEDIATELY, +}; + +use super::utils::{syscall, Overlapped}; +use super::{RwLockReadGuard, RwLockWriteGuard}; + +#[derive(Debug)] +pub struct RwLock<T: AsRawHandle> { + pub(crate) inner: T, +} + +impl<T: AsRawHandle> RwLock<T> { + #[inline] + pub fn new(inner: T) -> Self { + RwLock { inner } + } + + #[inline] + pub fn read(&self) -> io::Result<RwLockReadGuard<'_, T>> { + // See: https://stackoverflow.com/a/9186532, https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex + let handle = self.inner.as_raw_handle() as HANDLE; + let overlapped = Overlapped::zero(); + let flags = 0; + syscall(unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) })?; + Ok(RwLockReadGuard { lock: self }) + } + + #[inline] + pub fn try_read(&self) -> io::Result<RwLockReadGuard<'_, T>> { + let handle = self.inner.as_raw_handle() as HANDLE; + let overlapped = Overlapped::zero(); + let flags = LOCKFILE_FAIL_IMMEDIATELY; + + syscall(unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) }) + .map_err(|_| Error::from(ErrorKind::WouldBlock))?; + Ok(RwLockReadGuard { lock: self }) + } + + #[inline] + pub fn write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> { + // See: https://stackoverflow.com/a/9186532, https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex + let handle = self.inner.as_raw_handle() as HANDLE; + let overlapped = Overlapped::zero(); + let flags = LOCKFILE_EXCLUSIVE_LOCK; + syscall(unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) })?; + Ok(RwLockWriteGuard { lock: self }) + } + + #[inline] + pub fn try_write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> { + let handle = self.inner.as_raw_handle() as HANDLE; + let overlapped = Overlapped::zero(); + let flags = LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK; + + syscall(unsafe { LockFileEx(handle, flags, 0, 1, 0, overlapped.raw()) }) + .map_err(|_| Error::from(ErrorKind::WouldBlock))?; + Ok(RwLockWriteGuard { lock: self }) + } + + #[inline] + pub fn into_inner(self) -> T + where + T: Sized, + { + self.inner + } +} diff --git a/vendor/fd-lock/src/sys/windows/utils.rs b/vendor/fd-lock/src/sys/windows/utils.rs new file mode 100644 index 000000000..43656a083 --- /dev/null +++ b/vendor/fd-lock/src/sys/windows/utils.rs @@ -0,0 +1,33 @@ +use std::io; +use std::mem; + +use windows_sys::Win32::Foundation::BOOL; +use windows_sys::Win32::System::IO::OVERLAPPED; + +/// A wrapper around `OVERLAPPED` to provide "rustic" accessors and +/// initializers. +pub(crate) struct Overlapped(OVERLAPPED); + +impl Overlapped { + /// Creates a new zeroed out instance of an overlapped I/O tracking state. + /// + /// This is suitable for passing to methods which will then later get + /// notified via an I/O Completion Port. + pub(crate) fn zero() -> Overlapped { + Overlapped(unsafe { mem::zeroed() }) + } + + /// Gain access to the raw underlying data + pub(crate) fn raw(&self) -> *mut OVERLAPPED { + &self.0 as *const _ as *mut _ + } +} + +/// Convert a system call which returns a `BOOL` to an `io::Result`. +pub(crate) fn syscall(status: BOOL) -> std::io::Result<()> { + if status == 0 { + Err(io::Error::last_os_error()) + } else { + Ok(()) + } +} diff --git a/vendor/fd-lock/src/sys/windows/write_guard.rs b/vendor/fd-lock/src/sys/windows/write_guard.rs new file mode 100644 index 000000000..5494bd99e --- /dev/null +++ b/vendor/fd-lock/src/sys/windows/write_guard.rs @@ -0,0 +1,38 @@ +use windows_sys::Win32::Foundation::HANDLE; +use windows_sys::Win32::Storage::FileSystem::UnlockFile; + +use std::ops; +use std::os::windows::prelude::*; + +use super::utils::syscall; +use super::RwLock; + +#[derive(Debug)] +pub struct RwLockWriteGuard<'lock, T: AsRawHandle> { + pub(crate) lock: &'lock mut RwLock<T>, +} + +impl<T: AsRawHandle> ops::Deref for RwLockWriteGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.lock.inner + } +} + +impl<T: AsRawHandle> ops::DerefMut for RwLockWriteGuard<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.lock.inner + } +} + +impl<T: AsRawHandle> Drop for RwLockWriteGuard<'_, T> { + #[inline] + fn drop(&mut self) { + let handle = self.lock.inner.as_raw_handle() as HANDLE; + syscall(unsafe { UnlockFile(handle, 0, 0, 1, 0) }) + .expect("Could not unlock the file descriptor"); + } +} diff --git a/vendor/fd-lock/src/write_guard.rs b/vendor/fd-lock/src/write_guard.rs new file mode 100644 index 000000000..e218e3842 --- /dev/null +++ b/vendor/fd-lock/src/write_guard.rs @@ -0,0 +1,50 @@ +use std::ops; + +use crate::sys; + +/// RAII structure used to release the exclusive write access of a lock when +/// dropped. +/// +/// This structure is created by the [`write`] and [`try_write`] methods +/// on [`RwLock`]. +/// +/// [`write`]: crate::RwLock::write +/// [`try_write`]: crate::RwLock::try_write +/// [`RwLock`]: crate::RwLock +/// +/// # Panics +/// +/// Dropping this type may panic if the lock fails to unlock. +#[must_use = "if unused the RwLock will immediately unlock"] +#[derive(Debug)] +pub struct RwLockWriteGuard<'lock, T: sys::AsRaw> { + guard: sys::RwLockWriteGuard<'lock, T>, +} + +impl<'lock, T: sys::AsRaw> RwLockWriteGuard<'lock, T> { + pub(crate) fn new(guard: sys::RwLockWriteGuard<'lock, T>) -> Self { + Self { guard } + } +} + +impl<T: sys::AsRaw> ops::Deref for RwLockWriteGuard<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + self.guard.deref() + } +} + +impl<T: sys::AsRaw> ops::DerefMut for RwLockWriteGuard<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + self.guard.deref_mut() + } +} + +/// Release the lock. +impl<T: sys::AsRaw> Drop for RwLockWriteGuard<'_, T> { + #[inline] + fn drop(&mut self) {} +} |