extern crate std;
use core::fmt;
use std::{io, sync::Mutex};
use crate::UnsafeSeqLock;
pub struct MutexSeqLock<T> {
seq: UnsafeSeqLock<T>,
mutex: Mutex<()>,
}
impl<T> MutexSeqLock<T> {
pub const fn new(value: T) -> Self {
Self {
seq: UnsafeSeqLock::new(value),
mutex: Mutex::new(()),
}
}
}
impl<T: Copy> MutexSeqLock<T> {
pub fn read(&self) -> T {
unsafe { self.seq.read() }
}
pub fn read_version(&self) -> (u64, T) {
unsafe { self.seq.read_version() }
}
pub fn try_read(&self) -> Option<T> {
unsafe { self.seq.try_read() }
}
pub fn try_read_version(&self) -> Option<(u64, T)> {
unsafe { self.seq.try_read_version() }
}
pub fn write(&self, value: T) {
self.write_version(value);
}
pub fn write_version(&self, value: T) -> u64 {
let _guard = unsafe { self.mutex.lock().unwrap_unchecked() };
unsafe { self.seq.write_version(value) }
}
pub fn try_write(&self, value: T) -> Result<(), MutexSeqLockError> {
self.try_write_version(value).map(|_| ())
}
pub fn try_write_version(&self, value: T) -> Result<u64, MutexSeqLockError> {
match self.mutex.try_lock() {
Ok(_guard) => unsafe { Ok(self.seq.write_version(value)) },
Err(_) => Err(MutexSeqLockError),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct MutexSeqLockError;
impl fmt::Display for MutexSeqLockError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("operation would block")
}
}
impl From<MutexSeqLockError> for io::ErrorKind {
fn from(MutexSeqLockError: MutexSeqLockError) -> Self {
io::ErrorKind::WouldBlock
}
}
impl From<MutexSeqLockError> for io::Error {
fn from(value: MutexSeqLockError) -> Self {
io::Error::new(value.into(), value)
}
}
impl std::error::Error for MutexSeqLockError {}