Skip to content

Commit

Permalink
tests: Add further testing
Browse files Browse the repository at this point in the history
Co-authored-by: Jacob Rothstein <hi@jbr.me>
Signed-off-by: John Nunley <dev@notgull.net>
  • Loading branch information
notgull and jbr committed Apr 19, 2024
1 parent 434b390 commit 23b90f3
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 78 deletions.
53 changes: 33 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:

env:
CARGO_INCREMENTAL: 0
CARGO_NET_GIT_FETCH_WITH_CLI: true
CARGO_NET_RETRY: 10
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
Expand All @@ -26,42 +27,52 @@ defaults:

jobs:
test:
runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
rust: [nightly, beta, stable]
include:
- rust: stable
- rust: beta
- rust: nightly
- rust: nightly
target: i686-unknown-linux-gnu
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- name: Install cross-compilation tools
uses: taiki-e/setup-cross-toolchain-action@v1
with:
target: ${{ matrix.target }}
if: matrix.target != ''
- run: cargo build --all --all-features --all-targets
- run: cargo test --all
- run: cargo test --all --release
- run: cargo test --no-default-features --tests
- run: cargo test --no-default-features --tests --release
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
- run: rustup target add thumbv7m-none-eabi
- name: Run cargo check (without dev-dependencies to catch missing feature flags)
if: startsWith(matrix.rust, 'nightly')
run: cargo check -Z features=dev_dep
- run: cargo test
run: cargo hack build --all --no-dev-deps

msrv:
runs-on: ubuntu-latest
strategy:
matrix:
# When updating this, the reminder to update the minimum supported
# Rust version in Cargo.toml.
rust: ['1.39']
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
- run: cargo build
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
- run: cargo hack build --all --rust-version
- run: cargo hack build --all --no-default-features --rust-version

clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable
- run: cargo clippy --all-features --all-targets
- run: cargo clippy --all --all-features --all-targets

fmt:
runs-on: ubuntu-latest
Expand All @@ -77,10 +88,12 @@ jobs:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup toolchain install nightly --component miri && rustup default nightly
- run: cargo miri test
env:
MIRIFLAGS: -Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation
RUSTFLAGS: ${{ env.RUSTFLAGS }} -Z randomize-layout
- run: |
echo "MIRIFLAGS=-Zmiri-strict-provenance -Zmiri-symbolic-alignment-check -Zmiri-disable-isolation" >>"${GITHUB_ENV}"
echo "RUSTFLAGS=${RUSTFLAGS} -Z randomize-layout" >>"${GITHUB_ENV}"
- run: cargo miri test --all
- run: cargo miri test --no-default-features --tests
- run: cargo miri test --no-default-features --features portable-atomic --tests

security_audit:
permissions:
Expand All @@ -89,7 +102,7 @@ jobs:
issues: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# https://github.com/rustsec/audit-check/issues/2
- uses: rustsec/audit-check@master
with:
Expand Down
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
name = "event-listener"
# When publishing a new version:
# - Update CHANGELOG.md
# - Create "v2.x.y" git tag
# - Create "v5.x.y" git tag
version = "5.3.0"
authors = ["Stjepan Glavina <stjepang@gmail.com>"]
authors = ["Stjepan Glavina <stjepang@gmail.com>", "John Nunley <dev@notgull.net>"]
edition = "2021"
rust-version = "1.56"
rust-version = "1.63"
description = "Notify async tasks or threads"
license = "Apache-2.0 OR MIT"
repository = "https://github.com/smol-rs/event-listener"
Expand All @@ -21,7 +21,7 @@ portable-atomic = ["portable-atomic-crate", "portable-atomic-util"]

[dependencies]
portable-atomic-crate = { version = "1.6.0", package = "portable-atomic", optional = true }
portable-atomic-util = { version = "0.1.5", optional = true }
portable-atomic-util = { version = "0.1.5", optional = true, features = ["alloc"] }

[dev-dependencies]
futures = { version = "0.3", default-features = false, features = ["std"] }
Expand All @@ -32,6 +32,7 @@ waker-fn = "1"
[[bench]]
name = "bench"
harness = false
required-features = ["std"]

[lib]
bench = false
11 changes: 4 additions & 7 deletions benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
use criterion::{criterion_group, criterion_main, Criterion};
use event_listener::{Event, Listener};
use std::iter;

const COUNT: usize = 8000;

fn bench_events(c: &mut Criterion) {
c.bench_function("notify_and_wait", |b| {
let ev = Event::new();
let mut handles = Vec::with_capacity(COUNT);
b.iter(|| {
let mut handles = Vec::with_capacity(COUNT);

for _ in 0..COUNT {
handles.push(ev.listen());
}

handles.extend(iter::repeat_with(|| ev.listen()).take(COUNT));
ev.notify(COUNT);

for handle in handles {
for handle in handles.drain(..) {
handle.wait();
}
});
Expand Down
4 changes: 1 addition & 3 deletions examples/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,7 @@ impl<T> Mutex<T> {
}
Some(l) => {
// Wait until a notification is received.
if l.wait_deadline(deadline).is_none() {
return None;
}
l.wait_deadline(deadline)?;
}
}
}
Expand Down
61 changes: 31 additions & 30 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@
)]
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]

use loom::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
use loom::Arc;
use crate::loom::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
use crate::loom::Arc;
use notify::{GenericNotify, Internal, NotificationPrivate};

use std::cell::{Cell, UnsafeCell};
Expand All @@ -91,7 +91,6 @@ use std::sync::{Mutex, MutexGuard, TryLockError};
use std::task::{Context, Poll, Waker};
use std::thread::{self, Thread};
use std::time::{Duration, Instant};
use std::usize;

mod notify;
pub use notify::{IntoNotification, Notification};
Expand Down Expand Up @@ -385,24 +384,6 @@ impl Event {
pub fn notify_additional_relaxed(&self, n: usize) -> usize {
self.notify(n.additional().relaxed())
}
}

impl<T> Event<T> {
/// Creates a new [`Event`] with a tag.
///
/// # Examples
///
/// ```
/// use event_listener::Event;
///
/// let event = Event::<usize>::with_tag();
/// ```
#[inline]
pub const fn with_tag() -> Event<T> {
Event {
inner: AtomicPtr::new(ptr::null_mut()),
}
}

/// Return the listener count by acquiring a lock.
///
Expand Down Expand Up @@ -430,15 +411,32 @@ impl<T> Event<T> {
/// drop(listener2);
/// assert_eq!(event.total_listeners(), 0);
/// ```
#[cfg(feature = "std")]
#[inline]
pub fn total_listeners(&self) -> usize {
if let Some(inner) = self.try_inner() {
inner.total_listeners()
inner.lock().len
} else {
0
}
}
}

impl<T> Event<T> {
/// Creates a new [`Event`] with a tag.
///
/// # Examples
///
/// ```
/// use event_listener::Event;
///
/// let event = Event::<usize>::with_tag();
/// ```
#[inline]
pub const fn with_tag() -> Event<T> {
Event {
inner: AtomicPtr::new(ptr::null_mut()),
}
}

/// Returns a guard listening for a notification.
///
Expand Down Expand Up @@ -504,7 +502,7 @@ impl<T> Event<T> {
if let Some(inner) = self.try_inner() {
let limit = if notify.is_additional(Internal::new()) {
// Notify if there is at least one unnotified listener.
std::usize::MAX
usize::MAX
} else {
// Notify if there is at least one unnotified listener and the number of notified
// listeners is less than `n`.
Expand Down Expand Up @@ -535,7 +533,8 @@ impl<T> Event<T> {
/// ```
#[inline]
pub fn is_notified(&self) -> bool {
self.try_inner().map_or(false, |inner| inner.notified.load(Ordering::Acquire) > 0)
self.try_inner()
.map_or(false, |inner| inner.notified.load(Ordering::Acquire) > 0)
}

/// Returns a reference to the inner state if it was initialized.
Expand Down Expand Up @@ -614,11 +613,13 @@ impl<T> Drop for Event<T> {
impl fmt::Debug for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let inner = match self.try_inner() {
None => return f
.debug_tuple("Event")
.field(&format_args!("<uninitialized>"))
.finish(),
Some(inner) => inner
None => {
return f
.debug_tuple("Event")
.field(&format_args!("<uninitialized>"))
.finish()
}
Some(inner) => inner,
};

let guard = match inner.list.try_lock() {
Expand Down
12 changes: 1 addition & 11 deletions src/notify.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! The `Notification` trait for specifying notification.

#[cfg(feature = "std")]
use core::fmt;

use crate::loom::atomic::{self, Ordering};
Expand Down Expand Up @@ -161,15 +160,13 @@ where
}

/// Use a tag to notify listeners.
#[cfg(feature = "std")]
#[derive(Debug, Clone)]
#[doc(hidden)]
pub struct Tag<N: ?Sized, T> {
tag: T,
inner: N,
}

#[cfg(feature = "std")]
impl<N: ?Sized, T> Tag<N, T> {
/// Create a new `Tag` with the given tag and notification.
fn new(tag: T, inner: N) -> Self
Expand All @@ -180,7 +177,6 @@ impl<N: ?Sized, T> Tag<N, T> {
}
}

#[cfg(feature = "std")]
impl<N, T> NotificationPrivate for Tag<N, T>
where
N: Notification + ?Sized,
Expand All @@ -206,14 +202,12 @@ where
}

/// Use a function to generate a tag to notify listeners.
#[cfg(feature = "std")]
#[doc(hidden)]
pub struct TagWith<N: ?Sized, F> {
tag: F,
inner: N,
}

#[cfg(feature = "std")]
impl<N: fmt::Debug, F> fmt::Debug for TagWith<N, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TagWith")
Expand All @@ -223,15 +217,13 @@ impl<N: fmt::Debug, F> fmt::Debug for TagWith<N, F> {
}
}

#[cfg(feature = "std")]
impl<N, F> TagWith<N, F> {
/// Create a new `TagFn` with the given tag function and notification.
fn new(tag: F, inner: N) -> Self {
Self { tag, inner }
}
}

#[cfg(feature = "std")]
impl<N, F, T> NotificationPrivate for TagWith<N, F>
where
N: Notification + ?Sized,
Expand Down Expand Up @@ -490,7 +482,6 @@ pub trait IntoNotification: __private::Sealed {
/// assert_eq!(listener1.wait(), true);
/// assert_eq!(listener2.wait(), false);
/// ```
#[cfg(feature = "std")]
fn tag<T: Clone>(self, tag: T) -> Tag<Self::Notify, T>
where
Self: Sized + IntoNotification<Tag = ()>,
Expand Down Expand Up @@ -524,7 +515,6 @@ pub trait IntoNotification: __private::Sealed {
/// assert_eq!(listener1.wait(), true);
/// assert_eq!(listener2.wait(), false);
/// ```
#[cfg(feature = "std")]
fn tag_with<T, F>(self, tag: F) -> TagWith<Self::Notify, F>
where
Self: Sized + IntoNotification<Tag = ()>,
Expand Down Expand Up @@ -568,7 +558,7 @@ impl_for_numeric_types! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
/// Equivalent to `atomic::fence(Ordering::SeqCst)`, but in some cases faster.
#[inline]
pub(super) fn full_fence() {
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri), not(loom)))]
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri)))]
{
use core::{arch::asm, cell::UnsafeCell};
// HACK(stjepang): On x86 architectures there are two different ways of executing
Expand Down
Loading

0 comments on commit 23b90f3

Please sign in to comment.