improve locking (#204)

This commit is contained in:
Joel 2022-04-29 22:04:14 +02:00 committed by GitHub
parent dbec6c179a
commit 8f32487a12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 20 additions and 13 deletions

View File

@ -1,14 +1,17 @@
use lock_api::GuardSend; use lock_api::GuardSend;
use std::sync::atomic::{AtomicU32, Ordering}; use std::hint;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering};
const EXCLUSIVE_BIT: u32 = 1 << 31; const USIZE_BITS: usize = mem::size_of::<usize>() * 8;
const EXCLUSIVE_BIT: usize = 1 << (USIZE_BITS - 1);
pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>; pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>; pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;
pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>; pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>;
pub struct RawRwLock { pub struct RawRwLock {
data: AtomicU32, data: AtomicUsize,
} }
unsafe impl lock_api::RawRwLock for RawRwLock { unsafe impl lock_api::RawRwLock for RawRwLock {
@ -16,49 +19,53 @@ unsafe impl lock_api::RawRwLock for RawRwLock {
#[allow(clippy::declare_interior_mutable_const)] #[allow(clippy::declare_interior_mutable_const)]
const INIT: Self = RawRwLock { const INIT: Self = RawRwLock {
data: AtomicU32::new(0), data: AtomicUsize::new(0),
}; };
fn lock_shared(&self) { fn lock_shared(&self) {
while !self.try_lock_shared() {} while !self.try_lock_shared() {
hint::spin_loop();
}
} }
fn try_lock_shared(&self) -> bool { fn try_lock_shared(&self) -> bool {
let x = self.data.load(Ordering::SeqCst); let x = self.data.load(Ordering::Acquire);
if x & EXCLUSIVE_BIT != 0 { if x & EXCLUSIVE_BIT != 0 {
return false; return false;
} }
let y = x + 1; let y = x + 1;
self.data self.data
.compare_exchange(x, y, Ordering::SeqCst, Ordering::SeqCst) .compare_exchange(x, y, Ordering::Release, Ordering::Relaxed)
.is_ok() .is_ok()
} }
unsafe fn unlock_shared(&self) { unsafe fn unlock_shared(&self) {
self.data.fetch_sub(1, Ordering::SeqCst); self.data.fetch_sub(1, Ordering::Release);
} }
fn lock_exclusive(&self) { fn lock_exclusive(&self) {
while !self.try_lock_exclusive() {} while !self.try_lock_exclusive() {
hint::spin_loop();
}
} }
fn try_lock_exclusive(&self) -> bool { fn try_lock_exclusive(&self) -> bool {
self.data self.data
.compare_exchange(0, EXCLUSIVE_BIT, Ordering::SeqCst, Ordering::SeqCst) .compare_exchange(0, EXCLUSIVE_BIT, Ordering::Release, Ordering::Relaxed)
.is_ok() .is_ok()
} }
unsafe fn unlock_exclusive(&self) { unsafe fn unlock_exclusive(&self) {
self.data.store(0, Ordering::SeqCst) self.data.store(0, Ordering::Release)
} }
fn is_locked(&self) -> bool { fn is_locked(&self) -> bool {
self.data.load(Ordering::SeqCst) != 0 self.data.load(Ordering::Acquire) != 0
} }
fn is_locked_exclusive(&self) -> bool { fn is_locked_exclusive(&self) -> bool {
self.data.load(Ordering::SeqCst) & EXCLUSIVE_BIT != 0 self.data.load(Ordering::Acquire) & EXCLUSIVE_BIT != 0
} }
} }