Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge recent changes from maint-0.5 branch into master #45

Merged
merged 21 commits into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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' }}
Expand Down
74 changes: 74 additions & 0 deletions .github/workflows/LinuxCrossCompileTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Linux cross compile tests

on:
push:
paths-ignore:
- '.devcontainer/**'
- '.gitpod.yml'
- '.vscode/**'
- 'tests/**'
pull_request:
paths-ignore:
- '.devcontainer/**'
- '.gitpod.yml'
- '.vscode/**'
- 'tests/**'
schedule:
# Run against the last commit on the default branch on Friday at 9pm (UTC?)
- cron: '0 21 * * 5'

jobs:
linux-cross:
runs-on: ubuntu-latest
strategy:
matrix:
platform:
- target: aarch64-unknown-linux-musl
- target: i686-unknown-linux-musl
- target: armv7-unknown-linux-musleabihf
# Platforms without AtomicU64 support.
- target: armv5te-unknown-linux-musleabi
cargo-opts: "--no-default-features" # Disable atomic64 feature.
- target: mips-unknown-linux-musl
cargo-opts: "--no-default-features" # Disable atomic64 feature.
- target: mipsel-unknown-linux-musl
cargo-opts: "--no-default-features" # Disable atomic64 feature.

steps:
- name: Checkout Moka
uses: actions/checkout@v2

- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
target: ${{ matrix.platform.target }}
override: true

- name: Remove integration tests
run: |
rm -rf tests
sed -i '/actix-rt\|async-std\|reqwest\|skeptic/d' Cargo.toml
cat Cargo.toml

- uses: Swatinem/rust-cache@v1

- name: cargo clean
uses: actions-rs/cargo@v1
with:
command: clean

- name: Run tests (no features)
uses: actions-rs/cargo@v1
with:
use-cross: true
command: test
args: --release --target ${{ matrix.platform.target }} ${{ matrix.platform.cargo-opts }}

- name: Run tests (future feature)
uses: actions-rs/cargo@v1
with:
use-cross: true
command: test
args: --release --features future --target ${{ matrix.platform.target }} ${{ matrix.platform.cargo-opts }}
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{
"rust-analyzer.cargo.features": ["future"],
"cSpell.words": [
"aarch",
"actix",
"ahash",
"benmanes",
"CLFU",
"clippy",
"compat",
"cpus",
"deqs",
"Deque",
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@
- Change `get_or_try_insert_with` to return a concrete error type rather
than a trait object. ([#23][gh-pull-0023], [#37][gh-pull-0037])

## Version 0.5.4

### Changed

- Restore quanta dependency on some 32-bit platforms such as
`armv5te-unknown-linux-musleabi` or `mips-unknown-linux-musl`.
([#42][gh-pull-0042])


## 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`)
([#38][gh-issue-0038])
- 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

Expand Down Expand Up @@ -112,6 +131,10 @@

[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-pull-0042]: https://github.com/moka-rs/moka/pull/42/
[gh-issue-0038]: https://github.com/moka-rs/moka/issues/38/
[gh-pull-0037]: https://github.com/moka-rs/moka/pull/37/
[gh-pull-0033]: https://github.com/moka-rs/moka/pull/33/
[gh-issue-0031]: https://github.com/moka-rs/moka/issues/31/
Expand Down
12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,24 @@ 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 = []

[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"
quanta = "0.9.3"
scheduled-thread-pool = "0.2"
thiserror = "1.0"
uuid = { version = "0.8", features = ["v4"] }
Expand Down
52 changes: 44 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<!--
Expand All @@ -334,6 +335,41 @@ 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[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 Moka uses 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 enable a fall-back implementation in Moka, so it will compile.


## Developing Moka

**Running All Tests**
Expand Down
20 changes: 10 additions & 10 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -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_atomic64.rs")]

#[cfg_attr(feature = "atomic64", path = "common/time_atomic64.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<Instant>;
fn set_last_accessed(&mut self, timestamp: Instant);
fn last_modified(&self) -> Option<Instant>;
fn set_last_modified(&mut self, timestamp: Instant);
}

pub(crate) fn u64_to_instant(ts: u64) -> Option<Instant> {
if ts == u64::MAX {
None
} else {
Some(unsafe { std::mem::transmute(ts) })
}
}
5 changes: 4 additions & 1 deletion src/common/thread_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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/seanmonstar/num_cpus/issues/69
let num_threads = num_cpus::get().max(1);
let pool =
ScheduledThreadPool::with_name(name.thread_name_template(), num_threads);
let t_pool = ThreadPool {
Expand Down
42 changes: 42 additions & 0 deletions src/common/time_atomic64.rs
Original file line number Diff line number Diff line change
@@ -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<Instant> {
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);
}
}
37 changes: 37 additions & 0 deletions src/common/time_compat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use parking_lot::RwLock;

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: RwLock<Option<Instant>>,
}

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<Instant> {
*self.instant.read()
}

pub(crate) fn set_instant(&self, instant: Instant) {
*self.instant.write() = Some(instant);
}
}
5 changes: 2 additions & 3 deletions src/future/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ where
self.base.reconfigure_for_testing();
}

fn set_expiration_clock(&self, clock: Option<quanta::Clock>) {
fn set_expiration_clock(&self, clock: Option<crate::common::time::Clock>) {
self.base.set_expiration_clock(clock);
}
}
Expand All @@ -747,10 +747,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]
Expand Down