fd_lock/
rw_lock.rs

1use crate::read_guard::RwLockReadGuard;
2use crate::sys;
3use crate::write_guard::RwLockWriteGuard;
4use std::io;
5
6/// Advisory reader-writer lock for files.
7///
8/// This type of lock allows a number of readers or at most one writer at any point
9/// in time. The write portion of this lock typically allows modification of the
10/// underlying data (exclusive access) and the read portion of this lock typically
11/// allows for read-only access (shared access).
12#[derive(Debug)]
13pub struct RwLock<T: sys::AsOpenFile> {
14    lock: sys::RwLock<T>,
15}
16
17impl<T: sys::AsOpenFile> RwLock<T> {
18    /// Create a new instance.
19    ///
20    /// # Examples
21    ///
22    /// ```no_run
23    /// use fd_lock::RwLock;
24    /// use std::fs::File;
25    ///
26    /// fn main() -> std::io::Result<()> {
27    ///     let mut f = RwLock::new(File::open("foo.txt")?);
28    ///     Ok(())
29    /// }
30    /// ```
31    #[inline]
32    pub fn new(inner: T) -> Self {
33        Self {
34            lock: sys::RwLock::new(inner),
35        }
36    }
37
38    /// Locks this lock with shared read access, blocking the current thread
39    /// until it can be acquired.
40    ///
41    /// The calling thread will be blocked until there are no more writers which
42    /// hold the lock. There may be other readers currently inside the lock when
43    /// this method returns. This method does not provide any guarantees with
44    /// respect to the ordering of whether contentious readers or writers will
45    /// acquire the lock first.
46    ///
47    /// Returns an RAII guard which will release this thread's shared access
48    /// once it is dropped.
49    ///
50    /// # Errors
51    ///
52    /// On Unix this may return an `ErrorKind::Interrupted` if the operation was
53    /// interrupted by a signal handler.
54    #[inline]
55    pub fn read(&self) -> io::Result<RwLockReadGuard<'_, T>> {
56        let guard = self.lock.read()?;
57        Ok(RwLockReadGuard::new(guard))
58    }
59
60    /// Attempts to acquire this lock with shared read access.
61    ///
62    /// If the access could not be granted at this time, then `Err` is returned.
63    /// Otherwise, an RAII guard is returned which will release the shared access
64    /// when it is dropped.
65    ///
66    /// This function does not block.
67    ///
68    /// This function does not provide any guarantees with respect to the ordering
69    /// of whether contentious readers or writers will acquire the lock first.
70    ///
71    /// # Errors
72    ///
73    /// If the lock is already held and `ErrorKind::WouldBlock` error is returned.
74    /// On Unix this may return an `ErrorKind::Interrupted` if the operation was
75    /// interrupted by a signal handler.
76    #[inline]
77    pub fn try_read(&self) -> io::Result<RwLockReadGuard<'_, T>> {
78        let guard = self.lock.try_read()?;
79        Ok(RwLockReadGuard::new(guard))
80    }
81
82    /// Locks this lock with exclusive write access, blocking the current thread
83    /// until it can be acquired.
84    ///
85    /// This function will not return while other writers or other readers
86    /// currently have access to the lock.
87    ///
88    /// Returns an RAII guard which will drop the write access of this rwlock
89    /// when dropped.
90    ///
91    /// # Errors
92    ///
93    /// On Unix this may return an `ErrorKind::Interrupted` if the operation was
94    /// interrupted by a signal handler.
95    #[inline]
96    pub fn write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> {
97        let guard = self.lock.write()?;
98        Ok(RwLockWriteGuard::new(guard))
99    }
100
101    /// Attempts to lock this lock with exclusive write access.
102    ///
103    /// If the lock could not be acquired at this time, then `Err` is returned.
104    /// Otherwise, an RAII guard is returned which will release the lock when
105    /// it is dropped.
106    ///
107    /// # Errors
108    ///
109    /// If the lock is already held and `ErrorKind::WouldBlock` error is returned.
110    /// On Unix this may return an `ErrorKind::Interrupted` if the operation was
111    /// interrupted by a signal handler.
112    #[inline]
113    pub fn try_write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> {
114        let guard = self.lock.try_write()?;
115        Ok(RwLockWriteGuard::new(guard))
116    }
117
118    /// Consumes this `RwLock`, returning the underlying data.
119    #[inline]
120    pub fn into_inner(self) -> T
121    where
122        T: Sized,
123    {
124        self.lock.into_inner()
125    }
126}