#[cfg(unix)]
use std::os::fd::AsRawFd;
use std::{
fs::File,
ops::{Deref, DerefMut},
};
use memmap2::MmapMut;
use crate::synchronizer::SynchronizerError;
#[allow(private_bounds)]
pub trait WriteLockStrategy<'a>: WriteLockStrategySealed<'a> {}
pub(crate) trait WriteLockStrategySealed<'a> {
type Guard: DerefMut<Target = MmapMut> + 'a;
fn new(mmap: MmapMut, file: File) -> Self;
fn read(&'a self) -> &'a [u8];
fn lock(&'a mut self) -> Result<Self::Guard, SynchronizerError>;
}
pub struct LockDisabled(MmapMut);
impl<'a> WriteLockStrategySealed<'a> for LockDisabled {
type Guard = DisabledGuard<'a>;
#[inline]
fn new(mmap: MmapMut, _file: File) -> Self {
Self(mmap)
}
#[inline]
fn read(&'a self) -> &'a [u8] {
&self.0
}
#[inline]
fn lock(&'a mut self) -> Result<Self::Guard, SynchronizerError> {
Ok(DisabledGuard(&mut self.0))
}
}
impl<'a> WriteLockStrategy<'a> for LockDisabled {}
pub struct DisabledGuard<'a>(&'a mut MmapMut);
impl<'a> Deref for DisabledGuard<'a> {
type Target = MmapMut;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl<'a> DerefMut for DisabledGuard<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.0
}
}
#[cfg(unix)]
pub struct SingleWriter {
mmap: MmapMut,
file: File,
locked: bool,
}
#[cfg(unix)]
impl<'a> WriteLockStrategySealed<'a> for SingleWriter {
type Guard = SingleWriterGuard<'a>;
#[inline]
fn new(mmap: MmapMut, file: File) -> Self {
Self {
mmap,
file,
locked: false,
}
}
#[inline]
fn read(&'a self) -> &'a [u8] {
&self.mmap
}
#[inline]
fn lock(&'a mut self) -> Result<Self::Guard, SynchronizerError> {
if self.locked {
return Ok(SingleWriterGuard(&mut self.mmap));
}
match unsafe { libc::flock(self.file.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) } {
0 => {
self.locked = true;
Ok(SingleWriterGuard(&mut self.mmap))
}
_ => Err(SynchronizerError::WriteLockConflict),
}
}
}
#[cfg(unix)]
impl<'a> WriteLockStrategy<'a> for SingleWriter {}
#[cfg(unix)]
pub struct SingleWriterGuard<'a>(&'a mut MmapMut);
#[cfg(unix)]
impl<'a> Deref for SingleWriterGuard<'a> {
type Target = MmapMut;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
#[cfg(unix)]
impl<'a> DerefMut for SingleWriterGuard<'a> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.0
}
}