diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 738c17e..b264aac 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -63,7 +63,7 @@ jobs:
- name: Install cargo-hack
run: cargo install cargo-hack
- name: Apply clippy lints
- run: cargo hack clippy --each-feature
+ run: cargo hack clippy --each-feature --include-features sync,async --exclude-no-default-features
# Run tests on some extra platforms
cross:
@@ -80,7 +80,6 @@ jobs:
- x86_64-pc-windows-gnu
- i686-unknown-linux-gnu
- powerpc64-unknown-linux-gnu
- - mips64-unknown-linux-gnuabi64
- riscv64gc-unknown-linux-gnu
runs-on: ubuntu-latest
steps:
@@ -134,7 +133,7 @@ jobs:
path: ~/.cargo
key: ${{ runner.os }}-coverage-dotcargo
- name: Run build
- run: cargo hack build --feature-powerset
+ run: cargo hack build --feature-powerset --include-features sync,async --exclude-no-default-features
test:
name: test
@@ -168,63 +167,63 @@ jobs:
path: ~/.cargo
key: ${{ runner.os }}-coverage-dotcargo
- name: Run test
- run: cargo hack test --feature-powerset
+ run: cargo hack test --feature-powerset --include-features sync,async --exclude-no-default-features
- sanitizer:
- name: sanitizer
- strategy:
- matrix:
- os:
- - ubuntu-latest
- - macos-latest
- - windows-latest
- runs-on: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v3
- - name: Cache cargo build and registry
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-sanitizer-${{ hashFiles('**/Cargo.lock') }}
- restore-keys: |
- ${{ runner.os }}-sanitizer-
- - name: Install Rust
- run: rustup update $nightly && rustup default $nightly
- - name: Install rust-src
- run: rustup component add rust-src
- - name: Install cargo-hack
- run: cargo install cargo-hack
- - name: ASAN / LSAN / TSAN
- run: ci/sanitizer.sh
+ # sanitizer:
+ # name: sanitizer
+ # strategy:
+ # matrix:
+ # os:
+ # - ubuntu-latest
+ # - macos-latest
+ # - windows-latest
+ # runs-on: ${{ matrix.os }}
+ # steps:
+ # - uses: actions/checkout@v3
+ # - name: Cache cargo build and registry
+ # uses: actions/cache@v3
+ # with:
+ # path: |
+ # ~/.cargo/registry
+ # ~/.cargo/git
+ # target
+ # key: ${{ runner.os }}-sanitizer-${{ hashFiles('**/Cargo.lock') }}
+ # restore-keys: |
+ # ${{ runner.os }}-sanitizer-
+ # - name: Install Rust
+ # run: rustup update $nightly && rustup default $nightly
+ # - name: Install rust-src
+ # run: rustup component add rust-src
+ # - name: Install cargo-hack
+ # run: cargo install cargo-hack
+ # - name: ASAN / LSAN / TSAN
+ # run: ci/sanitizer.sh
- miri:
- name: miri
- strategy:
- matrix:
- os:
- - ubuntu-latest
- - macos-latest
- - windows-latest
- runs-on: ${{ matrix.os }}
- steps:
- - uses: actions/checkout@v3
- - name: Cache cargo build and registry
- uses: actions/cache@v3
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- target
- key: ${{ runner.os }}-miri-${{ hashFiles('**/Cargo.lock') }}
- restore-keys: |
- ${{ runner.os }}-miri-
- - name: Install cargo-hack
- run: cargo install cargo-hack
- - name: Miri
- run: ci/miri.sh
+ # miri:
+ # name: miri
+ # strategy:
+ # matrix:
+ # os:
+ # - ubuntu-latest
+ # - macos-latest
+ # - windows-latest
+ # runs-on: ${{ matrix.os }}
+ # steps:
+ # - uses: actions/checkout@v3
+ # - name: Cache cargo build and registry
+ # uses: actions/cache@v3
+ # with:
+ # path: |
+ # ~/.cargo/registry
+ # ~/.cargo/git
+ # target
+ # key: ${{ runner.os }}-miri-${{ hashFiles('**/Cargo.lock') }}
+ # restore-keys: |
+ # ${{ runner.os }}-miri-
+ # - name: Install cargo-hack
+ # run: cargo install cargo-hack
+ # - name: Miri
+ # run: ci/miri.sh
# # valgrind
# valgrind:
@@ -296,8 +295,8 @@ jobs:
- build
- cross
- test
- - sanitizer
- - miri
+ # - sanitizer
+ # - miri
- docs
steps:
- uses: actions/checkout@v3
diff --git a/Cargo.toml b/Cargo.toml
index 2f549e7..ad77bac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -48,7 +48,6 @@ async-channel = { version = "1.8", optional = true }
async-io = { version = "1.12", optional = true }
crossbeam-channel = { version = "0.5", optional = true }
futures = { version = "0.3", optional = true }
-log = { version = "0.4", optional = true }
parking_lot = "0.12"
rand = "0.8"
serde = { version = "1", optional = true, features = ["derive"] }
diff --git a/README-zh_hans.md b/README-zh_hans.md
index f273932..82753d0 100644
--- a/README-zh_hans.md
+++ b/README-zh_hans.md
@@ -9,16 +9,16 @@
[English](README.md) | 简体中文
-[][Github-url]
-[][CI-url]
+[][Github-url]
+[][CI-url]
[][codecov-url]
[][doc-url]
[][crates-url]
-[][rustc-url]
+[][crates-url]
+
+
-[][license-apache-url]
-[][license-mit-url]
diff --git a/README.md b/README.md
index 1b1a310..ae367fb 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ A high performance thread-safe memory-bound Rust cache.
English | [简体中文](README-zh_hans.md)
-[][Github-url]
+[][Github-url]
[][CI-url]
[][codecov-url]
@@ -17,8 +17,8 @@ English | [简体中文](README-zh_hans.md)
[][crates-url]
[][crates-url]
-[][license-apache-url]
-[][license-mit-url]
+
+
diff --git a/ci/miri.sh b/ci/miri.sh
index 7ea1a2c..6e0637f 100755
--- a/ci/miri.sh
+++ b/ci/miri.sh
@@ -7,5 +7,5 @@ cargo miri setup
export MIRIFLAGS="-Zmiri-strict-provenance -Zmiri-disable-isolation -Zmiri-symbolic-alignment-check"
-cargo hack miri test --each-feature
+cargo hack miri test --each-feature --include-features sync,async --exclude-no-default-features
diff --git a/ci/sanitizer.sh b/ci/sanitizer.sh
index a21beb3..0acecdc 100755
--- a/ci/sanitizer.sh
+++ b/ci/sanitizer.sh
@@ -6,12 +6,12 @@ export ASAN_OPTIONS="detect_odr_violation=0 detect_leaks=0"
# Run address sanitizer with cargo-hack
RUSTFLAGS="-Z sanitizer=address" \
-cargo hack test --lib --each-feature
+cargo hack test --lib --each-feature --include-features sync,async --exclude-no-default-features
# Run leak sanitizer with cargo-hack
RUSTFLAGS="-Z sanitizer=leak" \
-cargo hack test --lib --each-feature
+cargo hack test --lib --each-feature --include-features sync,async --exclude-no-default-features
# Run thread sanitizer with cargo-hack
RUSTFLAGS="-Z sanitizer=thread" \
-cargo hack -Zbuild-std test --lib --each-feature
+cargo hack -Zbuild-std test --lib --each-feature --include-features sync,async --exclude-no-default-features
diff --git a/ci/test-stable.sh b/ci/test-stable.sh
deleted file mode 100755
index 2b95e2a..0000000
--- a/ci/test-stable.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-cmd="${1:-test}"
-
-# Run with all features
-cargo "${cmd}" --all-features
-
-cargo doc --no-deps --all-features
-
-if [[ "${RUST_VERSION}" == "nightly"* ]]; then
- # Check benchmarks
- cargo check --benches
-
- # Check minimal versions
- cargo clean
- cargo update -Zminimal-versions
- cargo check --all-features
-fi
\ No newline at end of file
diff --git a/src/cache.rs b/src/cache.rs
index dfd6d0d..0761dc3 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -198,6 +198,7 @@ macro_rules! impl_builder {
};
}
+#[cfg(feature = "sync")]
macro_rules! impl_cache {
($cache: ident, $builder: ident, $item: ident) => {
use crate::store::UpdateResult;
diff --git a/src/cache/builder.rs b/src/cache/builder.rs
index c79d218..4547d83 100644
--- a/src/cache/builder.rs
+++ b/src/cache/builder.rs
@@ -176,7 +176,7 @@ where
/// This is a fine-tuning mechanism and you probably won't have to touch this.
#[inline]
pub fn set_buffer_size(mut self, sz: usize) -> Self {
- self.insert_buffer_size = sz;
+ self.insert_buffer_size = sz;
self
}
diff --git a/src/lib.rs b/src/lib.rs
index 0292209..2c5fe57 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,175 +1,7 @@
-//!
-//!
Stretto
-//!
-//!
-//!
-//! ## Features
-//! * **Internal Mutability** - Do not need to use `Arc>` for concurrent code, you just need `Cache<...>` or `AsyncCache<...>`
-//! * **Sync and Async** - Stretto support sync and runtime agnostic async.
-//! * In sync, [`Cache`] starts two extra OS level threads. One is policy thread, the other is writing thread.
-//! * In async, [`AsyncCache`] starts two extra green threads. One is policy thread, the other is writing thread.
-//! * **Store policy** Stretto only store the value, which means the cache does not store the key.
-//! * **High Hit Ratios** - with Dgrpah's developers unique admission/eviction policy pairing, Stretto's performance is best in class.
-//! * **Eviction: SampledLFU** - on par with exact LRU and better performance on Search and Database traces.
-//! * **Admission: TinyLFU** - extra performance with little memory overhead (12 bits per counter).
-//! * **Fast Throughput** - use a variety of techniques for managing contention and the result is excellent throughput.
-//! * **Cost-Based Eviction** - any large new item deemed valuable can evict multiple smaller items (cost could be anything).
-//! * **Fully Concurrent** - you can use as many threads as you want with little throughput degradation.
-//! * **Metrics** - optional performance metrics for throughput, hit ratios, and other stats.
-//! * **Simple API** - just figure out your ideal [`CacheBuilder`] values and you're off and running.
-//!
-//! ## Table of Contents
-//!
-//! * [Usage](#Usage)
-//! * [Example](#Example)
-//! * [Sync](#Sync)
-//! * [Async](#Async)
-//! * [Config](#Config)
-//! * [num_counters](#num_counters)
-//! * [max_cost](#max_cost)
-//! * [key_builder](#key_builder)
-//! * [buffer_size](#buffer_size)
-//! * [metrics](#metrics)
-//! * [ignore_internal_cost](#ignore_internal_cost)
-//! * [cleanup_duration](#cleanup_duration)
-//! * [update_validator](#update_validator)
-//! * [callback](#callback)
-//! * [coster](#coster)
-//! * [hasher](#hasher)
-//!
-//! ## Usage
-//! ### Example
-//! Please see [examples](https://github.com/al8n/stretto/tree/main/examples) on github.
-//!
-//! ### Config
-//! The [`CacheBuilder`] or [`AsyncCacheBuilder`] struct is used when creating [`Cache`]/[`AsyncCache`] instances if you want to customize the [`Cache`]/[`AsyncCache`] settings.
-//!
-//! #### num_counters
-//!
-//! `num_counters` is the number of 4-bit access counters to keep for admission and eviction.
-//! Dgraph's developers have seen good performance in setting this to 10x the number of
-//! items you expect to keep in the cache when full.
-//!
-//! For example, if you expect each item to have a cost of 1 and `max_cost` is 100, set `num_counters` to 1,000.
-//! Or, if you use variable cost values but expect the cache to hold around 10,000 items when full,
-//! set num_counters to 100,000. The important thing is the *number of unique items* in the full cache,
-//! not necessarily the `max_cost` value.
-//!
-//! #### max_cost
-//!
-//! `max_cost` is how eviction decisions are made. For example,
-//! if max_cost is 100 and a new item with a cost of 1 increases total cache cost to 101,
-//! 1 item will be evicted.
-//!
-//! `max_cost` can also be used to denote the max size in bytes. For example,
-//! if max_cost is 1,000,000 (1MB) and the cache is full with 1,000 1KB items,
-//! a new item (that's accepted) would cause 5 1KB items to be evicted.
-//!
-//! `max_cost` could be anything as long as it matches how you're using the cost values when calling `insert`.
-//!
-//! #### key_builder
-//!
-//! [`KeyBuilder`] is the hashing algorithm used for every key. In Stretto, the Cache will never store the real key.
-//! The key will be processed by [`KeyBuilder`]. Stretto has two default built-in key builder,
-//! one is [`TransparentKeyBuilder`], the other is [`DefaultKeyBuilder`]. If your key implements [`TransparentKey`] trait,
-//! you can use [`TransparentKeyBuilder`] which is faster than [`DefaultKeyBuilder`]. Otherwise, you should use [`DefaultKeyBuilder`]
-//! You can also write your own key builder for the Cache, by implementing [`KeyBuilder`] trait.
-//!
-//! Note that if you want 128bit hashes you should use the full `(u64, u64)`,
-//! otherwise just fill the `u64` at the `0` position, and it will behave like
-//! any 64bit hash.
-//!
-//! #### buffer_size
-//!
-//! `buffer_size` is the size of the insert buffers. The Dgraph's developers find that 32 * 1024 gives a good performance.
-//!
-//! If for some reason you see insert performance decreasing with lots of contention (you shouldn't),
-//! try increasing this value in increments of 32 * 1024.
-//! This is a fine-tuning mechanism and you probably won't have to touch this.
-//!
-//! #### metrics
-//!
-//! Metrics is true when you want real-time logging of a variety of stats.
-//! The reason this is a CacheBuilder flag is because there's a 10% throughput performance overhead.
-//!
-//! #### ignore_internal_cost
-//!
-//! Set to true indicates to the cache that the cost of
-//! internally storing the value should be ignored. This is useful when the
-//! cost passed to set is not using bytes as units. Keep in mind that setting
-//! this to true will increase the memory usage.
-//!
-//! #### cleanup_duration
-//!
-//! The Cache will cleanup the expired values every 500ms by default.
-//!
-//! #### update_validator
-//!
-//! By default, the Cache will always update the value if the value already exists in the cache.
-//! [`UpdateValidator`] is a trait to support customized update policy (check if the value should be updated
-//! if the value already exists in the cache).
-//!
-//! #### callback
-//!
-//! [`CacheCallback`] is for customize some extra operations on values when related event happens.
-//!
-//! #### coster
-//!
-//! [`Coster`] is a trait you can pass to the [`CacheBuilder`] in order to evaluate
-//! item cost at runtime, and only for the [`insert`] calls that aren't dropped (this is
-//! useful if calculating item cost is particularly expensive, and you don't want to
-//! waste time on items that will be dropped anyways).
-//!
-//! To signal to Stretto that you'd like to use this [`Coster`] trait:
-//!
-//! 1. Set the [`Coster`] field to your own [`Coster`] implementation.
-//! 2. When calling [`insert`] for new items or item updates, use a cost of 0.
-//!
-//! #### hasher
-//!
-//! The hasher for the Cache, default is SipHasher.
-//!
-//! [Github-url]: https://github.com/al8n/stretto/
-//! [CI-url]: https://github.com/al8n/stretto/actions/workflows/ci.yml
-//! [doc-url]: https://docs.rs/stretto
-//! [crates-url]: https://crates.io/crates/stretto
-//! [codecov-url]: https://app.codecov.io/gh/al8n/stretto/
-//! [license-url]: https://opensource.org/licenses/Apache-2.0
-//! [license-apache-url]: https://opensource.org/licenses/Apache-2.0
-//! [license-mit-url]: https://opensource.org/licenses/MIT
-//! [rustc-image]: https://img.shields.io/badge/rustc-1.52.0--nightly%2B-orange.svg?style=for-the-badge&logo=Rust
-//! [rustc-url]: https://github.com/rust-lang/rust/blob/master/RELEASES.md
-//! [`KeyBuilder`]: trait.KeyBuilder.html
-//! [`TransparentKey`]: trait.TransparentKey.html
-//! [`TransparentKeyBuilder`]: struct.TransparentKeyBuilder.html
-//! [`DefaultKeyBuilder`]: struct.DefaultKeyBuilder.html
-//! [`CacheBuilder`]: struct.CacheBuilder.html
-//! [`AsyncCacheBuilder`]: struct.AsyncCacheBuilder.html
-//! [`insert`]: struct.Cache.html#method.insert
-//! [`UpdateValidator`]: trait.UpdateValidator.html
-//! [`CacheCallback`]: trait.CacheCallback.html
-//! [`Coster`]: trait.Coster.html
-//! [`Cache`]: struct.Cache.html
-//! [`AsyncCache`]: struct.AsyncCache.html
#![deny(missing_docs)]
#![allow(clippy::too_many_arguments, clippy::type_complexity)]
#![cfg_attr(docsrs, feature(doc_cfg))]
diff --git a/src/metrics.rs b/src/metrics.rs
index e441260..91b3ed8 100644
--- a/src/metrics.rs
+++ b/src/metrics.rs
@@ -421,7 +421,7 @@ impl MetricsInner {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
-use serde::ser::{Error, SerializeStruct};
+use serde::ser::SerializeStruct;
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
use serde::{Serialize, Serializer};
@@ -461,7 +461,6 @@ impl Serialize for MetricsInner {
}
}
-#[cfg(not(feature = "serde"))]
impl Display for MetricsInner {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut buf = Vec::new();
@@ -482,14 +481,6 @@ impl Display for MetricsInner {
}
}
-#[cfg(feature = "serde")]
-impl Display for MetricsInner {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- let str = serde_json::to_string_pretty(self).map_err(std::fmt::Error::custom)?;
- write!(f, "Metrics::Op {}", str)
- }
-}
-
fn new_histogram_bound() -> Vec {
(1..=HISTOGRAM_BOUND_SIZE as u64)
.map(|idx| (1 << idx) as f64)
@@ -541,15 +532,6 @@ mod test {
}
#[test]
- #[cfg(all(feature = "serde", feature = "serde_json"))]
- fn test_display() {
- let m = MetricsInner::new();
- let ms = serde_json::to_string_pretty(&m).unwrap();
- assert_eq!(format!("{}", m), format!("Metrics::Op {}", ms));
- }
-
- #[test]
- #[cfg(not(all(feature = "serde", feature = "serde_json")))]
fn test_display() {
let m = MetricsInner::new();
let exp = "Metrics::Op {
diff --git a/src/policy/test.rs b/src/policy/test.rs
index b1fdf34..2206622 100644
--- a/src/policy/test.rs
+++ b/src/policy/test.rs
@@ -1,166 +1,172 @@
use crate::metrics::Metrics;
-use crate::policy::{LFUPolicy, SampledLFU, TinyLFU};
+use crate::policy::{SampledLFU, TinyLFU};
use std::collections::hash_map::RandomState;
-use std::sync::Arc;
+
use std::time::Duration;
static WAIT: Duration = Duration::from_millis(100);
-use std::thread::sleep;
+#[cfg(feature = "sync")]
+mod sync_test {
+ use super::*;
+ use crate::policy::LFUPolicy;
+ use std::sync::Arc;
+ use std::thread::sleep;
-#[test]
-fn test_policy() {
- let _ = LFUPolicy::new(100, 10);
-}
+ #[test]
+ fn test_policy() {
+ let _ = LFUPolicy::new(100, 10);
+ }
-#[test]
-fn test_policy_metrics() {
- let mut p = LFUPolicy::new(100, 10).unwrap();
- p.collect_metrics(Arc::new(Metrics::new_op()));
- assert!(p.metrics.is_op());
- assert!(p.inner.lock().costs.metrics.is_op());
-}
+ #[test]
+ fn test_policy_metrics() {
+ let mut p = LFUPolicy::new(100, 10).unwrap();
+ p.collect_metrics(Arc::new(Metrics::new_op()));
+ assert!(p.metrics.is_op());
+ assert!(p.inner.lock().costs.metrics.is_op());
+ }
-#[test]
-fn test_policy_process_items() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.items_tx.send(vec![1, 2, 2]).unwrap();
- sleep(WAIT);
- let inner = p.inner.lock();
- assert_eq!(inner.admit.estimate(2), 2);
- assert_eq!(inner.admit.estimate(1), 1);
- drop(inner);
-
- p.stop_tx.send(()).unwrap();
- sleep(WAIT);
- assert!(p.push(vec![3, 3, 3]).is_err());
- let inner = p.inner.lock();
- assert_eq!(inner.admit.estimate(3), 0);
-}
+ #[test]
+ fn test_policy_process_items() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.items_tx.send(vec![1, 2, 2]).unwrap();
+ sleep(WAIT);
+ let inner = p.inner.lock();
+ assert_eq!(inner.admit.estimate(2), 2);
+ assert_eq!(inner.admit.estimate(1), 1);
+ drop(inner);
-#[test]
-fn test_policy_push() {
- let p = LFUPolicy::new(100, 10).unwrap();
- assert!(p.push(vec![]).unwrap());
-
- let mut keep_count = 0;
- (0..10).for_each(|_| {
- if p.push(vec![1, 2, 3, 4, 5]).unwrap() {
- keep_count += 1;
- }
- });
+ p.stop_tx.send(()).unwrap();
+ sleep(WAIT);
+ assert!(p.push(vec![3, 3, 3]).is_err());
+ let inner = p.inner.lock();
+ assert_eq!(inner.admit.estimate(3), 0);
+ }
- assert_ne!(0, keep_count);
-}
+ #[test]
+ fn test_policy_push() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ assert!(p.push(vec![]).unwrap());
-#[test]
-fn test_policy_add() {
- let p = LFUPolicy::new(1000, 100).unwrap();
- let (victims, added) = p.add(1, 101);
- assert!(victims.is_none());
- assert!(!added);
-
- let mut inner = p.inner.lock();
- inner.costs.increment(1, 1);
- inner.admit.increment(1);
- inner.admit.increment(2);
- inner.admit.increment(3);
- drop(inner);
-
- let (victims, added) = p.add(1, 1);
- assert!(victims.is_none());
- assert!(!added);
-
- let (victims, added) = p.add(2, 20);
- assert!(victims.is_none());
- assert!(added);
-
- let (victims, added) = p.add(3, 90);
- assert!(victims.is_some());
- assert!(added);
-
- let (victims, added) = p.add(4, 20);
- assert!(victims.is_some());
- assert!(!added);
-}
+ let mut keep_count = 0;
+ (0..10).for_each(|_| {
+ if p.push(vec![1, 2, 3, 4, 5]).unwrap() {
+ keep_count += 1;
+ }
+ });
-#[test]
-fn test_policy_has() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 1);
- assert!(p.contains(&1));
- assert!(!p.contains(&2));
-}
+ assert_ne!(0, keep_count);
+ }
-#[test]
-fn test_policy_del() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 1);
- p.remove(&1);
- p.remove(&2);
- assert!(!p.contains(&1));
- assert!(!p.contains(&2));
-}
+ #[test]
+ fn test_policy_add() {
+ let p = LFUPolicy::new(1000, 100).unwrap();
+ let (victims, added) = p.add(1, 101);
+ assert!(victims.is_none());
+ assert!(!added);
-#[test]
-fn test_policy_cap() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 1);
- assert_eq!(p.cap(), 9);
-}
+ let mut inner = p.inner.lock();
+ inner.costs.increment(1, 1);
+ inner.admit.increment(1);
+ inner.admit.increment(2);
+ inner.admit.increment(3);
+ drop(inner);
-#[test]
-fn test_policy_update() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 1);
- p.update(&1, 2);
- let inner = p.inner.lock();
- assert_eq!(inner.costs.key_costs.get(&1).unwrap(), &2);
-}
+ let (victims, added) = p.add(1, 1);
+ assert!(victims.is_none());
+ assert!(!added);
-#[test]
-fn test_policy_cost() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 2);
- assert_eq!(p.cost(&1), 2);
- assert_eq!(p.cost(&2), -1);
-}
+ let (victims, added) = p.add(2, 20);
+ assert!(victims.is_none());
+ assert!(added);
-#[test]
-fn test_policy_clear() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 1);
- p.add(2, 2);
- p.add(3, 3);
- p.clear();
-
- assert_eq!(p.cap(), 10);
- assert!(!p.contains(&2));
- assert!(!p.contains(&2));
- assert!(!p.contains(&3));
-}
+ let (victims, added) = p.add(3, 90);
+ assert!(victims.is_some());
+ assert!(added);
-#[test]
-fn test_policy_close() {
- let p = LFUPolicy::new(100, 10).unwrap();
- p.add(1, 1);
- let _ = p.close();
- sleep(WAIT);
- assert!(p.items_tx.send(vec![1]).is_err())
-}
+ let (victims, added) = p.add(4, 20);
+ assert!(victims.is_some());
+ assert!(!added);
+ }
-#[test]
-fn test_policy_push_after_close() {
- let p = LFUPolicy::new(100, 10).unwrap();
- let _ = p.close();
- assert!(!p.push(vec![1, 2]).unwrap());
-}
+ #[test]
+ fn test_policy_has() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 1);
+ assert!(p.contains(&1));
+ assert!(!p.contains(&2));
+ }
-#[test]
-fn test_policy_add_after_close() {
- let p = LFUPolicy::new(100, 10).unwrap();
- let _ = p.close();
- p.add(1, 1);
+ #[test]
+ fn test_policy_del() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 1);
+ p.remove(&1);
+ p.remove(&2);
+ assert!(!p.contains(&1));
+ assert!(!p.contains(&2));
+ }
+
+ #[test]
+ fn test_policy_cap() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 1);
+ assert_eq!(p.cap(), 9);
+ }
+
+ #[test]
+ fn test_policy_update() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 1);
+ p.update(&1, 2);
+ let inner = p.inner.lock();
+ assert_eq!(inner.costs.key_costs.get(&1).unwrap(), &2);
+ }
+
+ #[test]
+ fn test_policy_cost() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 2);
+ assert_eq!(p.cost(&1), 2);
+ assert_eq!(p.cost(&2), -1);
+ }
+
+ #[test]
+ fn test_policy_clear() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 1);
+ p.add(2, 2);
+ p.add(3, 3);
+ p.clear();
+
+ assert_eq!(p.cap(), 10);
+ assert!(!p.contains(&2));
+ assert!(!p.contains(&2));
+ assert!(!p.contains(&3));
+ }
+
+ #[test]
+ fn test_policy_close() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ p.add(1, 1);
+ let _ = p.close();
+ sleep(WAIT);
+ assert!(p.items_tx.send(vec![1]).is_err())
+ }
+
+ #[test]
+ fn test_policy_push_after_close() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ let _ = p.close();
+ assert!(!p.push(vec![1, 2]).unwrap());
+ }
+
+ #[test]
+ fn test_policy_add_after_close() {
+ let p = LFUPolicy::new(100, 10).unwrap();
+ let _ = p.close();
+ p.add(1, 1);
+ }
}
#[cfg(feature = "async")]
diff --git a/src/ring.rs b/src/ring.rs
index d260457..4fc2da2 100644
--- a/src/ring.rs
+++ b/src/ring.rs
@@ -4,14 +4,17 @@ use parking_lot::Mutex;
#[cfg(feature = "async")]
use crate::policy::AsyncLFUPolicy;
+#[cfg(feature = "sync")]
use crate::policy::LFUPolicy;
+#[cfg(feature = "sync")]
pub struct RingStripe {
cons: Arc>,
data: Mutex>,
capa: usize,
}
+#[cfg(feature = "sync")]
impl RingStripe
where
S: BuildHasher + Clone + 'static,
diff --git a/src/store.rs b/src/store.rs
index b327ebc..610ac3d 100644
--- a/src/store.rs
+++ b/src/store.rs
@@ -1,4 +1,3 @@
-use crate::policy::LFUPolicy;
use crate::ttl::{ExpirationMap, Time};
use crate::utils::{change_lifetime_const, SharedValue, ValueRef, ValueRefMut};
use crate::{CacheError, DefaultUpdateValidator, Item as CrateItem, UpdateValidator};
@@ -238,9 +237,10 @@ impl<
.map(|val| val.expiration)
}
+ #[cfg(feature = "sync")]
pub fn try_cleanup(
&self,
- policy: Arc>,
+ policy: Arc>,
) -> Result>, CacheError> {
let now = Time::now();
Ok(self