diff --git a/Cargo.lock b/Cargo.lock index 52714f5..edd3e40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,7 +22,7 @@ dependencies = [ "fastrand", "hashbrown", "lock_api", - "parking_lot_core", + "parking_lot", "pyo3", "pyo3-build-config", ] @@ -88,6 +88,16 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + [[package]] name = "parking_lot_core" version = "0.9.11" diff --git a/Cargo.toml b/Cargo.toml index 13256b8..6785152 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,9 +37,8 @@ features = ["macros", "extension-module"] [dependencies.cfg-if] version = "1.0.3" -[dependencies.parking_lot_core] -version = "0.9.11" -default-features = false +[dependencies.parking_lot] +version = "0.12.4" [dependencies.lock_api] version = "0.4.13" diff --git a/src/bridge/cache.rs b/src/bridge/cache.rs index b23ccec..6d1304b 100644 --- a/src/bridge/cache.rs +++ b/src/bridge/cache.rs @@ -4,14 +4,14 @@ use crate::common::PreHashObject; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct Cache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[allow(non_camel_case_types)] #[pyo3::pyclass(module = "cachebox._core")] pub struct cache_items { pub ptr: ObservedIterator, - pub iter: crate::mutex::Mutex)>>, + pub iter: crate::common::Mutex)>>, } #[pyo3::pymethods] @@ -22,7 +22,7 @@ impl Cache { let raw = crate::policies::nopolicy::NoPolicy::new(maxsize, capacity)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -205,7 +205,7 @@ impl Cache { let result = cache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), }; pyo3::Py::new(slf.py(), result) diff --git a/src/bridge/fifocache.rs b/src/bridge/fifocache.rs index 688cd37..67e3e7e 100644 --- a/src/bridge/fifocache.rs +++ b/src/bridge/fifocache.rs @@ -4,14 +4,14 @@ use crate::common::PreHashObject; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct FIFOCache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[allow(non_camel_case_types)] #[pyo3::pyclass(module = "cachebox._core")] pub struct fifocache_items { pub ptr: ObservedIterator, - pub iter: crate::mutex::Mutex, + pub iter: crate::common::Mutex, } #[pyo3::pymethods] @@ -22,7 +22,7 @@ impl FIFOCache { let raw = crate::policies::fifo::FIFOPolicy::new(maxsize, capacity)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -221,7 +221,7 @@ impl FIFOCache { let result = fifocache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), }; pyo3::Py::new(slf.py(), result) diff --git a/src/bridge/lfucache.rs b/src/bridge/lfucache.rs index a287482..5e97cf1 100644 --- a/src/bridge/lfucache.rs +++ b/src/bridge/lfucache.rs @@ -4,14 +4,14 @@ use crate::common::PreHashObject; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct LFUCache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[allow(non_camel_case_types)] #[pyo3::pyclass(module = "cachebox._core")] pub struct lfucache_items { pub ptr: ObservedIterator, - pub iter: crate::mutex::Mutex, + pub iter: crate::common::Mutex, } #[pyo3::pymethods] @@ -22,7 +22,7 @@ impl LFUCache { let raw = crate::policies::lfu::LFUPolicy::new(maxsize, capacity)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -234,7 +234,7 @@ impl LFUCache { let result = lfucache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), }; pyo3::Py::new(slf.py(), result) diff --git a/src/bridge/lrucache.rs b/src/bridge/lrucache.rs index 99f894d..305f57a 100644 --- a/src/bridge/lrucache.rs +++ b/src/bridge/lrucache.rs @@ -4,14 +4,14 @@ use crate::common::PreHashObject; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct LRUCache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[allow(non_camel_case_types)] #[pyo3::pyclass(module = "cachebox._core")] pub struct lrucache_items { pub ptr: ObservedIterator, - pub iter: crate::mutex::Mutex, + pub iter: crate::common::Mutex, } #[pyo3::pymethods] @@ -22,7 +22,7 @@ impl LRUCache { let raw = crate::policies::lru::LRUPolicy::new(maxsize, capacity)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -230,7 +230,7 @@ impl LRUCache { let result = lrucache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), }; pyo3::Py::new(slf.py(), result) diff --git a/src/bridge/rrcache.rs b/src/bridge/rrcache.rs index ebd746d..b0b37f9 100644 --- a/src/bridge/rrcache.rs +++ b/src/bridge/rrcache.rs @@ -5,7 +5,7 @@ use crate::common::PreHashObject; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct RRCache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[pyo3::pymethods] @@ -16,7 +16,7 @@ impl RRCache { let raw = crate::policies::random::RandomPolicy::new(maxsize, capacity)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -208,7 +208,7 @@ impl RRCache { let result = cache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), }; pyo3::Py::new(slf.py(), result) diff --git a/src/bridge/ttlcache.rs b/src/bridge/ttlcache.rs index ee2d4ae..c35899e 100644 --- a/src/bridge/ttlcache.rs +++ b/src/bridge/ttlcache.rs @@ -5,14 +5,14 @@ use crate::common::TimeToLivePair; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct TTLCache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[allow(non_camel_case_types)] #[pyo3::pyclass(module = "cachebox._core")] pub struct ttlcache_items { pub ptr: ObservedIterator, - pub iter: crate::mutex::Mutex, + pub iter: crate::common::Mutex, pub now: std::time::SystemTime, } @@ -24,7 +24,7 @@ impl TTLCache { let raw = crate::policies::ttl::TTLPolicy::new(maxsize, capacity, ttl)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -224,7 +224,7 @@ impl TTLCache { let result = ttlcache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), now: std::time::SystemTime::now(), }; diff --git a/src/bridge/vttlcache.rs b/src/bridge/vttlcache.rs index 1ea7a36..11927ac 100644 --- a/src/bridge/vttlcache.rs +++ b/src/bridge/vttlcache.rs @@ -5,14 +5,14 @@ use crate::common::TimeToLivePair; #[pyo3::pyclass(module = "cachebox._core", frozen)] pub struct VTTLCache { - raw: crate::mutex::Mutex, + raw: crate::common::Mutex, } #[allow(non_camel_case_types)] #[pyo3::pyclass(module = "cachebox._core")] pub struct vttlcache_items { pub ptr: ObservedIterator, - pub iter: crate::mutex::Mutex, + pub iter: crate::common::Mutex, pub now: std::time::SystemTime, } @@ -24,7 +24,7 @@ impl VTTLCache { let raw = crate::policies::vttl::VTTLPolicy::new(maxsize, capacity)?; let self_ = Self { - raw: crate::mutex::Mutex::new(raw), + raw: crate::common::Mutex::new(raw), }; Ok(self_) } @@ -224,7 +224,7 @@ impl VTTLCache { let result = vttlcache_items { ptr: ObservedIterator::new(slf.as_ptr(), state), - iter: crate::mutex::Mutex::new(iter), + iter: crate::common::Mutex::new(iter), now: std::time::SystemTime::now(), }; diff --git a/src/common.rs b/src/common.rs index d90aded..3fdf51c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -484,3 +484,7 @@ impl TimeToLivePair { } } } + +// Thanks to `Amanieu d'Antras` for this beautiful implementation. +// https://github.com/Amanieu/parking_lot/blob/eeb186c48c8e6433c10f7552ef1cd1d56e5c83b1/src/raw_mutex.rs +pub type Mutex = lock_api::Mutex; diff --git a/src/lib.rs b/src/lib.rs index 44e3749..1505e33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,6 @@ use pyo3::prelude::*; mod lazyheap; mod linked_list; -mod mutex; #[macro_use] mod common; diff --git a/src/mutex.rs b/src/mutex.rs deleted file mode 100644 index e218522..0000000 --- a/src/mutex.rs +++ /dev/null @@ -1,173 +0,0 @@ -//! Mutex lock -//! -//! Thanks to `Amanieu d'Antras` for this beautiful implementation. - -use core::sync::atomic::{AtomicU8, Ordering}; -use parking_lot_core::deadlock; -use parking_lot_core::{self, ParkResult, SpinWait, UnparkResult, UnparkToken, DEFAULT_PARK_TOKEN}; -use std::time::Instant; - -const TOKEN_NORMAL: UnparkToken = UnparkToken(0); -const TOKEN_HANDOFF: UnparkToken = UnparkToken(1); - -const LOCKED_BIT: u8 = 0b01; -const PARKED_BIT: u8 = 0b10; - -pub struct RawMutex { - state: AtomicU8, -} - -unsafe impl lock_api::RawMutex for RawMutex { - #[allow(clippy::declare_interior_mutable_const)] - const INIT: RawMutex = RawMutex { - state: AtomicU8::new(0), - }; - - type GuardMarker = lock_api::GuardSend; - - #[inline] - fn lock(&self) { - if self - .state - .compare_exchange_weak(0, LOCKED_BIT, Ordering::Acquire, Ordering::Relaxed) - .is_err() - { - self.lock_slow(None); - } - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; - } - - #[inline] - fn try_lock(&self) -> bool { - let mut state = self.state.load(Ordering::Relaxed); - loop { - if state & LOCKED_BIT != 0 { - return false; - } - match self.state.compare_exchange_weak( - state, - state | LOCKED_BIT, - Ordering::Acquire, - Ordering::Relaxed, - ) { - Ok(_) => { - unsafe { deadlock::acquire_resource(self as *const _ as usize) }; - return true; - } - Err(x) => state = x, - } - } - } - - #[inline] - unsafe fn unlock(&self) { - deadlock::release_resource(self as *const _ as usize); - if self - .state - .compare_exchange(LOCKED_BIT, 0, Ordering::Release, Ordering::Relaxed) - .is_ok() - { - return; - } - self.unlock_slow(false); - } - - #[inline] - fn is_locked(&self) -> bool { - let state = self.state.load(Ordering::Relaxed); - state & LOCKED_BIT != 0 - } -} - -impl RawMutex { - #[cold] - fn lock_slow(&self, timeout: Option) -> bool { - let mut spinwait = SpinWait::new(); - let mut state = self.state.load(Ordering::Relaxed); - loop { - if state & LOCKED_BIT == 0 { - match self.state.compare_exchange_weak( - state, - state | LOCKED_BIT, - Ordering::Acquire, - Ordering::Relaxed, - ) { - Ok(_) => return true, - Err(x) => state = x, - } - continue; - } - - if state & PARKED_BIT == 0 && spinwait.spin() { - state = self.state.load(Ordering::Relaxed); - continue; - } - - if state & PARKED_BIT == 0 { - if let Err(x) = self.state.compare_exchange_weak( - state, - state | PARKED_BIT, - Ordering::Relaxed, - Ordering::Relaxed, - ) { - state = x; - continue; - } - } - - let addr = self as *const _ as usize; - let validate = || self.state.load(Ordering::Relaxed) == LOCKED_BIT | PARKED_BIT; - let before_sleep = || {}; - let timed_out = |_, was_last_thread| { - if was_last_thread { - self.state.fetch_and(!PARKED_BIT, Ordering::Relaxed); - } - }; - - match unsafe { - parking_lot_core::park( - addr, - validate, - before_sleep, - timed_out, - DEFAULT_PARK_TOKEN, - timeout, - ) - } { - ParkResult::Unparked(TOKEN_HANDOFF) => return true, - ParkResult::Unparked(_) => (), - ParkResult::Invalid => (), - ParkResult::TimedOut => return false, - } - - spinwait.reset(); - state = self.state.load(Ordering::Relaxed); - } - } - - #[cold] - fn unlock_slow(&self, force_fair: bool) { - let addr = self as *const _ as usize; - let callback = |result: UnparkResult| { - if result.unparked_threads != 0 && (force_fair || result.be_fair) { - if !result.have_more_threads { - self.state.store(LOCKED_BIT, Ordering::Relaxed); - } - return TOKEN_HANDOFF; - } - - if result.have_more_threads { - self.state.store(PARKED_BIT, Ordering::Release); - } else { - self.state.store(0, Ordering::Release); - } - TOKEN_NORMAL - }; - - unsafe { - parking_lot_core::unpark_one(addr, callback); - } - } -} - -pub type Mutex = lock_api::Mutex;