use super::{LockHeldState, LockTestExt};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockResult};
pub struct FairRwLock<T> {
lock: RwLock<T>,
waiting_writers: AtomicUsize,
}
impl<T> FairRwLock<T> {
pub fn new(t: T) -> Self {
Self { lock: RwLock::new(t), waiting_writers: AtomicUsize::new(0) }
}
pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
self.waiting_writers.fetch_add(1, Ordering::Relaxed);
let res = self.lock.write();
self.waiting_writers.fetch_sub(1, Ordering::Relaxed);
res
}
pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
if self.waiting_writers.load(Ordering::Relaxed) != 0 {
let _write_queue_lock = self.lock.write();
}
self.lock.read()
}
#[allow(dead_code)]
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> {
self.lock.try_write()
}
}
impl<'a, T: 'a> LockTestExt<'a> for FairRwLock<T> {
#[inline]
fn held_by_thread(&self) -> LockHeldState {
LockHeldState::Unsupported
}
type ExclLock = RwLockWriteGuard<'a, T>;
#[inline]
fn unsafe_well_ordered_double_lock_self(&'a self) -> RwLockWriteGuard<'a, T> {
self.write().unwrap()
}
}