fd_lock/sys/unix/
rw_lock.rs

1use rustix::fd::AsFd;
2use rustix::fs::{flock, FlockOperation};
3use std::io::{self, Error, ErrorKind};
4
5use super::{RwLockReadGuard, RwLockWriteGuard};
6
7#[derive(Debug)]
8pub struct RwLock<T: AsFd> {
9    pub(crate) inner: T,
10}
11
12impl<T: AsFd> RwLock<T> {
13    #[inline]
14    pub fn new(inner: T) -> Self {
15        RwLock { inner }
16    }
17
18    #[inline]
19    pub fn write(&mut self) -> io::Result<RwLockWriteGuard<'_, T>> {
20        flock(&self.inner.as_fd(), FlockOperation::LockExclusive)?;
21        Ok(RwLockWriteGuard::new(self))
22    }
23
24    #[inline]
25    pub fn try_write(&mut self) -> Result<RwLockWriteGuard<'_, T>, Error> {
26        flock(
27            &self.inner.as_fd(),
28            FlockOperation::NonBlockingLockExclusive,
29        )
30        .map_err(|err| match err.kind() {
31            ErrorKind::AlreadyExists => ErrorKind::WouldBlock.into(),
32            _ => Error::from(err),
33        })?;
34        Ok(RwLockWriteGuard::new(self))
35    }
36
37    #[inline]
38    pub fn read(&self) -> io::Result<RwLockReadGuard<'_, T>> {
39        flock(&self.inner.as_fd(), FlockOperation::LockShared)?;
40        Ok(RwLockReadGuard::new(self))
41    }
42
43    #[inline]
44    pub fn try_read(&self) -> Result<RwLockReadGuard<'_, T>, Error> {
45        flock(&self.inner.as_fd(), FlockOperation::NonBlockingLockShared).map_err(
46            |err| match err.kind() {
47                ErrorKind::AlreadyExists => ErrorKind::WouldBlock.into(),
48                _ => Error::from(err),
49            },
50        )?;
51        Ok(RwLockReadGuard::new(self))
52    }
53
54    #[inline]
55    pub fn into_inner(self) -> T
56    where
57        T: Sized,
58    {
59        self.inner
60    }
61}