mirror of https://github.com/xacrimon/dashmap
improve locking (#204)
This commit is contained in:
parent
dbec6c179a
commit
8f32487a12
33
src/lock.rs
33
src/lock.rs
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue