Skip to content

Commit

Permalink
feat: Add portable-atomic feature
Browse files Browse the repository at this point in the history
portable-atomic-util now provides `std::task::Wake` equivalent: taiki-e/portable-atomic#145
This allows crates like waker-fn to support targets without atomics.
  • Loading branch information
taiki-e authored May 9, 2024
1 parent 6101041 commit 1bd72cd
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ jobs:
if: startsWith(matrix.rust, 'nightly')
run: cargo check -Z features=dev_dep
- run: cargo test
- run: cargo test --features portable-atomic

msrv:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -82,6 +83,10 @@ jobs:
env:
MIRIFLAGS: -Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation
RUSTFLAGS: ${{ env.RUSTFLAGS }} -Z randomize-layout
- run: cargo miri test --features portable-atomic
env:
MIRIFLAGS: -Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation
RUSTFLAGS: ${{ env.RUSTFLAGS }} -Z randomize-layout

security_audit:
permissions:
Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ documentation = "https://docs.rs/waker-fn"
keywords = ["async", "waker", "wake", "closure", "callback"]
categories = ["concurrency"]
exclude = ["/.*"]

[features]
# Uses portable-atomic polyfill atomics on targets without them
portable-atomic = ["portable-atomic-util"]

[dependencies]
portable-atomic-util = { version = "0.2", optional = true, default-features = false, features = ["alloc"] }
21 changes: 19 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
html_logo_url = "https://raw.githubusercontent.com/smol-rs/smol/master/assets/images/logo_fullsize_transparent.png"
)]

#[cfg(not(feature = "portable-atomic"))]
extern crate alloc;

use alloc::sync::Arc;
use alloc::task::Wake;
#[cfg(not(feature = "portable-atomic"))]
use alloc::{sync::Arc, task::Wake};
use core::task::Waker;
#[cfg(feature = "portable-atomic")]
use portable_atomic_util::{task::Wake, Arc};

/// Converts a closure into a [`Waker`].
///
Expand All @@ -38,6 +41,7 @@ pub fn waker_fn<F: Fn() + Send + Sync + 'static>(f: F) -> Waker {

struct Helper<F>(F);

#[cfg(not(feature = "portable-atomic"))]
impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
fn wake(self: Arc<Self>) {
(self.0)();
Expand All @@ -47,3 +51,16 @@ impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
(self.0)();
}
}
// Note: Unlike std::task::Wake, all methods take `this:` instead of `self:`.
// This is because using portable_atomic_util::Arc as a receiver requires the
// unstable arbitrary_self_types feature.
#[cfg(feature = "portable-atomic")]
impl<F: Fn() + Send + Sync + 'static> Wake for Helper<F> {
fn wake(this: Arc<Self>) {
(this.0)();
}

fn wake_by_ref(this: &Arc<Self>) {
(this.0)();
}
}

0 comments on commit 1bd72cd

Please sign in to comment.