diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7c2f70d2..2cd07db0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -68,6 +68,15 @@ jobs: env: RUSTFLAGS: '--cfg skeptic' + - name: Run tests (future, without atomic64) + uses: actions-rs/cargo@v1 + if: ${{ matrix.rust != '1.45.2' }} + with: + command: test + args: --release --no-default-features --features future + env: + RUSTFLAGS: '--cfg skeptic' + - name: Run UI tests (future, trybuild) uses: actions-rs/cargo@v1 if: ${{ matrix.rust == 'stable' }} diff --git a/.vscode/settings.json b/.vscode/settings.json index 9ba3d92d..d133ad48 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,13 @@ { "rust-analyzer.cargo.features": ["future"], "cSpell.words": [ + "aarch", "actix", "ahash", "benmanes", "CLFU", "clippy", + "compat", "cpus", "deqs", "Deque", diff --git a/CHANGELOG.md b/CHANGELOG.md index a8d9cf54..59dfff33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Moka — Change Log +## Version 0.5.3 + +### Added + +- Add support for some 32-bit platforms where `std::sync::atomic::AtomicU64` is not + provided. (e.g. `armv5te-unknown-linux-musleabi` or `mips-unknown-linux-musl`) + - On these platforms, you will need to disable the default features of Moka. + See [the relevant section][resolving-error-on-32bit] of the README. + + ## Version 0.5.2 ### Fixed @@ -104,6 +114,9 @@ [caffeine-git]: https://github.com/ben-manes/caffeine +[resolving-error-on-32bit]: https://github.com/moka-rs/moka#resolving-compile-errors-on-some-32-bit-platforms + +[gh-issue-0038]: https://github.com/moka-rs/moka/issues/38/ [gh-pull-0033]: https://github.com/moka-rs/moka/pull/33/ [gh-issue-0031]: https://github.com/moka-rs/moka/issues/31/ [gh-pull-0030]: https://github.com/moka-rs/moka/pull/30/ diff --git a/Cargo.toml b/Cargo.toml index 3c8d9d2f..713a69c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "moka" -version = "0.5.2" +version = "0.5.3" authors = ["Tatsuya Kawano "] edition = "2018" @@ -20,16 +20,23 @@ build = "build.rs" features = ["future"] [features] -default = [] +default = ["atomic64"] + +# Enable this feature to use `moka::future::Cache`. future = ["async-io", "async-lock"] +# This feature is enabled by default. Disable it when the target platform does not +# support `std::sync::atomic::AtomicU64`. (e.g. `armv5te-unknown-linux-musleabi` +# or `mips-unknown-linux-musl`) +# https://github.com/moka-rs/moka#resolving-compile-errors-on-some-32-bit-platforms +atomic64 = ["quanta"] + [dependencies] crossbeam-channel = "0.5" moka-cht = "0.4.2" num_cpus = "1.13" once_cell = "1.7" parking_lot = "0.11" -quanta = "0.9" scheduled-thread-pool = "0.2" thiserror = "1.0" uuid = { version = "0.8", features = ["v4"] } @@ -37,6 +44,7 @@ uuid = { version = "0.8", features = ["v4"] } # Optional dependencies async-io = { version = "1.4", optional = true } async-lock = { version = "2.4", optional = true } +quanta = { version = "0.9", optional = true } [dev-dependencies] actix-rt2 = { package = "actix-rt", version = "2", default-features = false } diff --git a/README.md b/README.md index 0e646fd7..77ef0edd 100644 --- a/README.md +++ b/README.md @@ -317,14 +317,15 @@ available on crates.io, such as the [aHash][ahash-crate] crate. This crate's minimum supported Rust versions (MSRV) are the followings: -| Enabled Feature | MSRV | -|:---------------------|:------------| -| no feature (default) | Rust 1.45.2 | -| `future` | Rust 1.46.0 | - -If no feature is enabled, MSRV will be updated conservatively. When using other -features, like `future`, MSRV might be updated more frequently, up to the latest -stable. In both cases, increasing MSRV is _not_ considered a semver-breaking +| Feature | Enabled by default? | MSRV | +|:-----------|:-------------------:|:-----------:| +| no feature | | Rust 1.45.2 | +| `atomic64` | yes | Rust 1.45.2 | +| `future` | | Rust 1.46.0 | + +If only the default features are enabled, MSRV will be updated conservatively. When +using other features, like `future`, MSRV might be updated more frequently, up to the +latest stable. In both cases, increasing MSRV is _not_ considered a semver-breaking change. +## Resolving Compile Errors on Some 32-bit Platforms + +On some 32-bit target platforms including the followings, you may encounter compile +errors in quanta crate and Moka itself. + +- `armv5te-unknown-linux-musleabi` +- `mips-unknown-linux-musl` +- `mipsel-unknown-linux-musl` + +```console +error[E0599]: no method named `fetch_add` found for struct `Arc>` in the current scope + --> ... /quanta-0.9.2/src/mock.rs:48:21 + | +48 | self.offset.fetch_add(amount.into_nanos()); + | ^^^^^^^^^ method not found in `Arc>` +``` + +```console +error[E0432]: unresolved import `std::sync::atomic::AtomicU64` + --> ... /moka-0.5.3/src/sync.rs:10:30 + | +10 | atomic::{AtomicBool, AtomicU64, Ordering}, + | ^^^^^^^^^ + | | + | no `AtomicU64` in `sync::atomic` +``` + +These errors occur because `std::sync::atomic::AtomicU64` type is not provided on +these platforms but both quanta and Moka use it. + +You can resolve the errors by disabling the default features of Moka. Edit your +Cargo.toml to add `default-features = false` option to the dependency declaration. + +```toml:Cargo.toml +[dependencies] +moka = { version = "0.5", default-feautures = false } +# Or +moka = { version = "0.5", default-feautures = false, features = ["future"] } +``` + +This will remove quanta from the dependencies and enable a fall-back implementation +in Moka, so it will compile. + + ## Developing Moka **Running All Tests** diff --git a/src/common.rs b/src/common.rs index 12c4793b..00ac4a67 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,22 +1,22 @@ -use quanta::Instant; - pub(crate) mod deque; pub(crate) mod error; pub(crate) mod frequency_sketch; pub(crate) mod thread_pool; pub(crate) mod unsafe_weak_pointer; +// targe_has_atomic is more convenient but yet unstable (Rust 1.55) +// https://github.com/rust-lang/rust/issues/32976 +// #[cfg_attr(target_has_atomic = "64", path = "common/time_quanta.rs")] + +#[cfg_attr(feature = "atomic64", path = "common/time_quanta.rs")] +#[cfg_attr(not(feature = "atomic64"), path = "common/time_compat.rs")] +pub(crate) mod time; + +use time::Instant; + pub(crate) trait AccessTime { fn last_accessed(&self) -> Option; fn set_last_accessed(&mut self, timestamp: Instant); fn last_modified(&self) -> Option; fn set_last_modified(&mut self, timestamp: Instant); } - -pub(crate) fn u64_to_instant(ts: u64) -> Option { - if ts == u64::MAX { - None - } else { - Some(unsafe { std::mem::transmute(ts) }) - } -} diff --git a/src/common/thread_pool.rs b/src/common/thread_pool.rs index 21ee5045..3550eafb 100644 --- a/src/common/thread_pool.rs +++ b/src/common/thread_pool.rs @@ -53,7 +53,10 @@ impl ThreadPoolRegistry { // and insert a new pool. let mut pools = REGISTRY.pools.write(); pools.entry(name).or_insert_with(|| { - let num_threads = num_cpus::get(); + // Some platforms may return 0. In that case, use 1. + // https://github.com/moka-rs/moka/pull/39#issuecomment-916888859 + // https://github.com/rust-lang/futures-rs/pull/1835 + let num_threads = num_cpus::get().max(1); let pool = ScheduledThreadPool::with_name(name.thread_name_template(), num_threads); let t_pool = ThreadPool { diff --git a/src/common/time_compat.rs b/src/common/time_compat.rs new file mode 100644 index 00000000..4d4a7b31 --- /dev/null +++ b/src/common/time_compat.rs @@ -0,0 +1,105 @@ +use std::{ + cmp::Ordering, + ops::Add, + sync::Arc, + time::{Duration, Instant as StdInstant}, +}; + +use parking_lot::RwLock; + +#[derive(Clone, Copy, PartialEq, Eq)] +pub(crate) struct Instant(StdInstant); + +impl Instant { + pub(crate) fn now() -> Self { + Self(StdInstant::now()) + } +} + +impl Add for Instant { + type Output = Instant; + + fn add(self, other: Duration) -> Self::Output { + let instant = self + .0 + .checked_add(other) + .expect("overflow when adding duration to instant"); + Self(instant) + } +} + +impl PartialOrd for Instant { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Instant { + fn cmp(&self, other: &Self) -> Ordering { + self.0.cmp(&other.0) + } +} + +pub(crate) struct AtomicInstant { + instant: RwLock>, +} + +impl Default for AtomicInstant { + fn default() -> Self { + Self { + instant: RwLock::new(None), + } + } +} + +impl AtomicInstant { + pub(crate) fn reset(&self) { + *self.instant.write() = None; + } + + pub(crate) fn is_set(&self) -> bool { + self.instant.read().is_some() + } + + pub(crate) fn instant(&self) -> Option { + *self.instant.read() + } + + pub(crate) fn set_instant(&self, instant: Instant) { + *self.instant.write() = Some(instant); + } +} + +pub(crate) struct Clock(Arc); + +impl Clock { + #[cfg(test)] + pub(crate) fn mock() -> (Clock, Arc) { + let mock = Arc::new(Mock::default()); + let clock = Clock(Arc::clone(&mock)); + (clock, mock) + } + + pub(crate) fn now(&self) -> Instant { + Instant(*self.0.now.read()) + } +} + +pub(crate) struct Mock { + now: RwLock, +} + +impl Default for Mock { + fn default() -> Self { + Self { + now: RwLock::new(StdInstant::now()), + } + } +} + +#[cfg(test)] +impl Mock { + pub(crate) fn increment(&self, amount: Duration) { + *self.now.write() += amount; + } +} diff --git a/src/common/time_quanta.rs b/src/common/time_quanta.rs new file mode 100644 index 00000000..50c8686d --- /dev/null +++ b/src/common/time_quanta.rs @@ -0,0 +1,42 @@ +use std::sync::atomic::{AtomicU64, Ordering}; + +pub(crate) type Instant = quanta::Instant; +pub(crate) type Clock = quanta::Clock; + +#[cfg(test)] +pub(crate) type Mock = quanta::Mock; + +pub(crate) struct AtomicInstant { + instant: AtomicU64, +} + +impl Default for AtomicInstant { + fn default() -> Self { + Self { + instant: AtomicU64::new(std::u64::MAX), + } + } +} + +impl AtomicInstant { + pub(crate) fn reset(&self) { + self.instant.store(std::u64::MAX, Ordering::Release); + } + + pub(crate) fn is_set(&self) -> bool { + self.instant.load(Ordering::Acquire) != u64::MAX + } + + pub(crate) fn instant(&self) -> Option { + let ts = self.instant.load(Ordering::Acquire); + if ts == u64::MAX { + None + } else { + Some(unsafe { std::mem::transmute(ts) }) + } + } + + pub(crate) fn set_instant(&self, instant: Instant) { + self.instant.store(instant.as_u64(), Ordering::Release); + } +} diff --git a/src/future/cache.rs b/src/future/cache.rs index 76c94162..178f058f 100644 --- a/src/future/cache.rs +++ b/src/future/cache.rs @@ -749,7 +749,7 @@ where self.base.reconfigure_for_testing(); } - fn set_expiration_clock(&self, clock: Option) { + fn set_expiration_clock(&self, clock: Option) { self.base.set_expiration_clock(clock); } } @@ -758,10 +758,9 @@ where #[cfg(test)] mod tests { use super::{Cache, ConcurrentCacheExt}; - use crate::future::CacheBuilder; + use crate::{common::time::Clock, future::CacheBuilder}; use async_io::Timer; - use quanta::Clock; use std::time::Duration; #[tokio::test] diff --git a/src/lib.rs b/src/lib.rs index bd77a6f6..6f708149 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,15 +57,16 @@ //! //! This crate's minimum supported Rust versions (MSRV) are the followings: //! -//! | Enabled Feature | MSRV | -//! |:---------------------|:------------| -//! | no feature (default) | Rust 1.45.2 | -//! | `future` | Rust 1.46.0 | -//! -//! If no crate feature is enabled, MSRV will be updated conservatively. When using -//! features like `future`, MSRV might be updated more frequently, up to the latest -//! stable. In both cases, increasing MSRV is _not_ considered a semver-breaking -//! change. +//! | Feature | Enabled by default? | MSRV | +//! |:-----------|:-------------------:|:-----------:| +//! | no feature | | Rust 1.45.2 | +//! | `atomic64` | yes | Rust 1.45.2 | +//! | `future` | | Rust 1.46.0 | +//! +//! If only the default features are enabled, MSRV will be updated conservatively. +//! When using other features, like `future`, MSRV might be updated more frequently, +//! up to the latest stable. In both cases, increasing MSRV is _not_ considered a +//! semver-breaking change. //! //! # Implementation Details //! diff --git a/src/sync.rs b/src/sync.rs index 7fa63299..03999861 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -1,13 +1,16 @@ //! Provides thread-safe, blocking cache implementations. -use crate::common::{deque::DeqNode, u64_to_instant, AccessTime}; +use crate::common::{ + deque::DeqNode, + time::{AtomicInstant, Instant}, + AccessTime, +}; use parking_lot::Mutex; -use quanta::Instant; use std::{ ptr::NonNull, sync::{ - atomic::{AtomicBool, AtomicU64, Ordering}, + atomic::{AtomicBool, Ordering}, Arc, }, }; @@ -63,27 +66,27 @@ impl Clone for KeyHash { pub(crate) struct KeyDate { pub(crate) key: Arc, - pub(crate) timestamp: Arc, + pub(crate) timestamp: Arc, } impl KeyDate { - pub(crate) fn new(key: Arc, timestamp: Arc) -> Self { + pub(crate) fn new(key: Arc, timestamp: Arc) -> Self { Self { key, timestamp } } pub(crate) fn timestamp(&self) -> Option { - u64_to_instant(self.timestamp.load(Ordering::Acquire)) + self.timestamp.instant() } } pub(crate) struct KeyHashDate { pub(crate) key: Arc, pub(crate) hash: u64, - pub(crate) timestamp: Arc, + pub(crate) timestamp: Arc, } impl KeyHashDate { - pub(crate) fn new(kh: KeyHash, timestamp: Arc) -> Self { + pub(crate) fn new(kh: KeyHash, timestamp: Arc) -> Self { Self { key: kh.key, hash: kh.hash, @@ -109,8 +112,8 @@ unsafe impl Send for DeqNodes {} pub(crate) struct ValueEntry { pub(crate) value: V, is_admitted: Arc, - last_accessed: Arc, - last_modified: Arc, + last_accessed: Arc, + last_modified: Arc, nodes: Mutex>, } @@ -119,8 +122,8 @@ impl ValueEntry { Self { value, is_admitted: Arc::new(AtomicBool::new(false)), - last_accessed: Arc::new(AtomicU64::new(std::u64::MAX)), - last_modified: Arc::new(AtomicU64::new(std::u64::MAX)), + last_accessed: Default::default(), + last_modified: Default::default(), nodes: Mutex::new(DeqNodes { access_order_q_node: None, write_order_q_node: None, @@ -141,8 +144,8 @@ impl ValueEntry { // To prevent this updated ValueEntry from being evicted by a expiration policy, // set the max value to the timestamps. They will be replaced with the real // timestamps when applying writes. - last_accessed.store(std::u64::MAX, Ordering::Release); - last_modified.store(std::u64::MAX, Ordering::Release); + last_accessed.reset(); + last_modified.reset(); Self { value, is_admitted: Arc::clone(&other.is_admitted), @@ -160,11 +163,11 @@ impl ValueEntry { self.is_admitted.store(value, Ordering::Release); } - pub(crate) fn raw_last_accessed(&self) -> Arc { + pub(crate) fn raw_last_accessed(&self) -> Arc { Arc::clone(&self.last_accessed) } - pub(crate) fn raw_last_modified(&self) -> Arc { + pub(crate) fn raw_last_modified(&self) -> Arc { Arc::clone(&self.last_modified) } @@ -202,24 +205,22 @@ impl ValueEntry { impl AccessTime for Arc> { #[inline] fn last_accessed(&self) -> Option { - u64_to_instant(self.last_accessed.load(Ordering::Acquire)) + self.last_accessed.instant() } #[inline] fn set_last_accessed(&mut self, timestamp: Instant) { - self.last_accessed - .store(timestamp.as_u64(), Ordering::Release); + self.last_accessed.set_instant(timestamp); } #[inline] fn last_modified(&self) -> Option { - u64_to_instant(self.last_modified.load(Ordering::Acquire)) + self.last_modified.instant() } #[inline] fn set_last_modified(&mut self, timestamp: Instant) { - self.last_modified - .store(timestamp.as_u64(), Ordering::Release); + self.last_modified.set_instant(timestamp); } } @@ -236,28 +237,24 @@ impl AccessTime for DeqNode> { #[inline] fn last_modified(&self) -> Option { - u64_to_instant(self.element.timestamp.load(Ordering::Acquire)) + self.element.timestamp.instant() } #[inline] fn set_last_modified(&mut self, timestamp: Instant) { - self.element - .timestamp - .store(timestamp.as_u64(), Ordering::Release); + self.element.timestamp.set_instant(timestamp); } } impl AccessTime for DeqNode> { #[inline] fn last_accessed(&self) -> Option { - u64_to_instant(self.element.timestamp.load(Ordering::Acquire)) + self.element.timestamp.instant() } #[inline] fn set_last_accessed(&mut self, timestamp: Instant) { - self.element - .timestamp - .store(timestamp.as_u64(), Ordering::Release); + self.element.timestamp.set_instant(timestamp); } #[inline] diff --git a/src/sync/base_cache.rs b/src/sync/base_cache.rs index ab87c1a9..b1a54718 100644 --- a/src/sync/base_cache.rs +++ b/src/sync/base_cache.rs @@ -8,6 +8,7 @@ use crate::{ common::{ deque::{CacheRegion, DeqNode, Deque}, frequency_sketch::FrequencySketch, + time::{AtomicInstant, Clock, Instant}, AccessTime, }, PredicateError, @@ -15,7 +16,6 @@ use crate::{ use crossbeam_channel::{Receiver, Sender, TrySendError}; use parking_lot::{Mutex, RwLock}; -use quanta::{Clock, Instant}; use std::{ borrow::Borrow, collections::hash_map::RandomState, @@ -24,7 +24,7 @@ use std::{ ptr::NonNull, rc::Rc, sync::{ - atomic::{AtomicBool, AtomicU64, AtomicU8, Ordering}, + atomic::{AtomicBool, AtomicU8, Ordering}, Arc, }, time::Duration, @@ -140,7 +140,7 @@ where } Some((arc_key, entry)) => { let i = &self.inner; - let (ttl, tti, va) = (&i.time_to_live(), &i.time_to_idle(), i.valid_after()); + let (ttl, tti, va) = (&i.time_to_live(), &i.time_to_idle(), &i.valid_after()); let now = i.current_time_from_expiration_clock(); if is_expired_entry_wo(ttl, va, &entry, now) @@ -339,7 +339,7 @@ where } } - pub(crate) fn set_expiration_clock(&self, clock: Option) { + pub(crate) fn set_expiration_clock(&self, clock: Option) { self.inner.set_expiration_clock(clock); } } @@ -358,7 +358,7 @@ pub(crate) struct Inner { write_op_ch: Receiver>, time_to_live: Option, time_to_idle: Option, - valid_after: AtomicU64, + valid_after: AtomicInstant, invalidator_enabled: bool, invalidator: RwLock>>, has_expiration_clock: AtomicBool, @@ -411,7 +411,7 @@ where write_op_ch, time_to_live, time_to_idle, - valid_after: AtomicU64::new(0), + valid_after: AtomicInstant::default(), invalidator_enabled, // When enabled, this field will be set later via the set_invalidator method. invalidator: RwLock::new(None), @@ -478,20 +478,18 @@ where } #[inline] - fn valid_after(&self) -> Instant { - let ts = self.valid_after.load(Ordering::Acquire); - unsafe { std::mem::transmute(ts) } + fn valid_after(&self) -> Option { + self.valid_after.instant() } #[inline] fn set_valid_after(&self, timestamp: Instant) { - self.valid_after - .store(timestamp.as_u64(), Ordering::Release); + self.valid_after.set_instant(timestamp); } #[inline] fn has_valid_after(&self) -> bool { - self.valid_after.load(Ordering::Acquire) > 0 + self.valid_after.is_set() } #[inline] @@ -749,8 +747,8 @@ where &self, kh: KeyHash, entry: &Arc>, - raw_last_accessed: Arc, - raw_last_modified: Arc, + raw_last_accessed: Arc, + raw_last_modified: Arc, deqs: &mut Deques, ) { let key = Arc::clone(&kh.key); @@ -822,7 +820,7 @@ where now: Instant, ) { let tti = &self.time_to_idle; - let va = self.valid_after(); + let va = &self.valid_after(); for _ in 0..batch_size { // Peek the front node of the deque and check if it is expired. let (key, _ts) = deq @@ -881,7 +879,7 @@ where #[inline] fn remove_expired_wo(&self, deqs: &mut Deques, batch_size: usize, now: Instant) { let ttl = &self.time_to_live; - let va = self.valid_after(); + let va = &self.valid_after(); for _ in 0..batch_size { let (key, _ts) = deqs .write_order @@ -1019,7 +1017,7 @@ where .unwrap_or(0) } - fn set_expiration_clock(&self, clock: Option) { + fn set_expiration_clock(&self, clock: Option) { let mut exp_clock = self.expiration_clock.write(); if let Some(clock) = clock { *exp_clock = Some(clock); @@ -1037,13 +1035,15 @@ where #[inline] fn is_expired_entry_ao( time_to_idle: &Option, - valid_after: Instant, + valid_after: &Option, entry: &impl AccessTime, now: Instant, ) -> bool { if let Some(ts) = entry.last_accessed() { - if ts < valid_after { - return true; + if let Some(va) = valid_after { + if ts < *va { + return true; + } } if let Some(tti) = time_to_idle { return ts + *tti <= now; @@ -1055,13 +1055,15 @@ fn is_expired_entry_ao( #[inline] fn is_expired_entry_wo( time_to_live: &Option, - valid_after: Instant, + valid_after: &Option, entry: &impl AccessTime, now: Instant, ) -> bool { if let Some(ts) = entry.last_modified() { - if ts < valid_after { - return true; + if let Some(va) = valid_after { + if ts < *va { + return true; + } } if let Some(ttl) = time_to_live { return ts + *ttl <= now; diff --git a/src/sync/cache.rs b/src/sync/cache.rs index d045556b..d95aa9c0 100644 --- a/src/sync/cache.rs +++ b/src/sync/cache.rs @@ -648,7 +648,7 @@ where self.base.reconfigure_for_testing(); } - pub(crate) fn set_expiration_clock(&self, clock: Option) { + pub(crate) fn set_expiration_clock(&self, clock: Option) { self.base.set_expiration_clock(clock); } } @@ -657,9 +657,8 @@ where #[cfg(test)] mod tests { use super::{Cache, ConcurrentCacheExt}; - use crate::sync::CacheBuilder; + use crate::{common::time::Clock, sync::CacheBuilder}; - use quanta::Clock; use std::time::Duration; #[test] diff --git a/src/sync/invalidator.rs b/src/sync/invalidator.rs index 8f3985fe..e0d77d9b 100644 --- a/src/sync/invalidator.rs +++ b/src/sync/invalidator.rs @@ -3,6 +3,7 @@ use crate::{ common::{ thread_pool::{PoolName, ThreadPool, ThreadPoolRegistry}, + time::Instant, unsafe_weak_pointer::UnsafeWeakPointer, AccessTime, }, @@ -12,13 +13,12 @@ use crate::{ use super::{base_cache::Inner, PredicateId, PredicateIdStr, ValueEntry}; use parking_lot::{Mutex, RwLock}; -use quanta::Instant; use std::{ collections::HashMap, hash::{BuildHasher, Hash}, marker::PhantomData, sync::{ - atomic::{AtomicBool, AtomicU64, Ordering}, + atomic::{AtomicBool, Ordering}, Arc, Weak, }, time::Duration, diff --git a/src/sync/segment.rs b/src/sync/segment.rs index 67c6bd77..42554ad4 100644 --- a/src/sync/segment.rs +++ b/src/sync/segment.rs @@ -324,7 +324,7 @@ where let mut exp_clock = MockExpirationClock::default(); for segment in self.inner.segments.iter() { - let (clock, mock) = quanta::Clock::mock(); + let (clock, mock) = crate::common::time::Clock::mock(); segment.set_expiration_clock(Some(clock)); exp_clock.mocks.push(mock); } @@ -337,7 +337,7 @@ where #[cfg(test)] #[derive(Default)] struct MockExpirationClock { - mocks: Vec>, + mocks: Vec>, } #[cfg(test)] diff --git a/src/unsync.rs b/src/unsync.rs index b3dd871c..64dd284e 100644 --- a/src/unsync.rs +++ b/src/unsync.rs @@ -8,9 +8,8 @@ use std::{ptr::NonNull, rc::Rc}; pub use builder::CacheBuilder; pub use cache::Cache; -use quanta::Instant; -use crate::common::{deque::DeqNode, AccessTime}; +use crate::common::{deque::DeqNode, time::Instant, AccessTime}; pub(crate) struct KeyDate { pub(crate) key: Rc, diff --git a/src/unsync/cache.rs b/src/unsync/cache.rs index 94d0ac03..96a0df5b 100644 --- a/src/unsync/cache.rs +++ b/src/unsync/cache.rs @@ -2,10 +2,10 @@ use super::{deques::Deques, KeyDate, KeyHashDate, ValueEntry}; use crate::common::{ deque::{CacheRegion, DeqNode, Deque}, frequency_sketch::FrequencySketch, + time::{Clock, Instant}, AccessTime, }; -use quanta::{Clock, Instant}; use std::{ borrow::Borrow, collections::{hash_map::RandomState, HashMap}, @@ -581,7 +581,7 @@ where K: Hash + Eq, S: BuildHasher + Clone, { - fn set_expiration_clock(&mut self, clock: Option) { + fn set_expiration_clock(&mut self, clock: Option) { self.expiration_clock = clock; } } @@ -590,9 +590,8 @@ where #[cfg(test)] mod tests { use super::Cache; - use crate::unsync::CacheBuilder; + use crate::{common::time::Clock, unsync::CacheBuilder}; - use quanta::Clock; use std::time::Duration; #[test]