Skip to content

Commit 70afc24

Browse files
jbrnotgull
authored andcommitted
feat: remove loom implementation from the revert PR
1 parent ed02521 commit 70afc24

File tree

7 files changed

+60
-360
lines changed

7 files changed

+60
-360
lines changed

Diff for: .github/workflows/ci.yml

-10
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,3 @@ jobs:
100100
with:
101101
token: ${{ secrets.GITHUB_TOKEN }}
102102

103-
loom:
104-
runs-on: ubuntu-latest
105-
steps:
106-
- uses: actions/checkout@v4
107-
- name: Install Rust
108-
run: rustup update stable
109-
- name: Loom tests
110-
run: RUSTFLAGS="--cfg=loom" cargo test --release --test loom --features loom
111-
- name: Loom tests for lock-free
112-
run: RUSTFLAGS="--cfg=loom" cargo test --no-default-features --release --test loom --features loom

Diff for: Cargo.toml

-3
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ futures-lite = "2.3.0"
2828
criterion = { version = "0.3.4", default-features = false, features = ["cargo_bench_support"] }
2929
waker-fn = "1"
3030

31-
[target.'cfg(loom)'.dependencies]
32-
loom = { version = "0.7", optional = true }
33-
3431
[[bench]]
3532
name = "bench"
3633
harness = false

Diff for: src/lib.rs

+41-97
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,12 @@
7878
#![no_std]
7979
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
8080

81-
#[cfg(all(
82-
not(all(feature = "std", loom)),
83-
any(not(feature = "std"), not(feature = "portable-atomic"))
84-
))]
81+
#[cfg(any(not(feature = "std"), not(feature = "portable-atomic")))]
8582
extern crate alloc;
8683

84+
#[cfg(feature = "std")]
8785
extern crate std;
8886

89-
use loom::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
90-
use loom::Arc;
91-
use notify::{Internal, NotificationPrivate};
92-
9387
use core::fmt;
9488
use core::future::Future;
9589
use core::mem::ManuallyDrop;
@@ -98,6 +92,10 @@ use core::pin::Pin;
9892
use core::ptr;
9993
use core::task::{Context, Poll};
10094
use core::usize;
95+
use notify::{Internal, NotificationPrivate};
96+
97+
use crate::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
98+
use crate::sync::Arc;
10199

102100
#[cfg(all(feature = "std", not(target_family = "wasm")))]
103101
use std::time::{Duration, Instant};
@@ -108,22 +106,6 @@ mod notify;
108106
pub(crate) use linked_list::Inner;
109107
pub use notify::{IntoNotification, Notification};
110108

111-
/// Make the given function const if the given condition is true.
112-
macro_rules! const_fn {
113-
(
114-
const_if: #[cfg($($cfg:tt)+)];
115-
$(#[$($attr:tt)*])*
116-
$vis:vis const fn $($rest:tt)*
117-
) => {
118-
#[cfg($($cfg)+)]
119-
$(#[$($attr)*])*
120-
$vis const fn $($rest)*
121-
#[cfg(not($($cfg)+))]
122-
$(#[$($attr)*])*
123-
$vis fn $($rest)*
124-
};
125-
}
126-
127109
/// Create a stack-based event listener for an [`Event`].
128110
///
129111
/// [`EventListener`] allocates the listener on the heap. While this works for most use cases, in
@@ -258,21 +240,18 @@ impl<T> UnwindSafe for Event<T> {}
258240
impl<T> RefUnwindSafe for Event<T> {}
259241

260242
impl Event {
261-
const_fn! {
262-
const_if: #[cfg(not(loom))];
263-
/// Creates a new [`Event`].
264-
///
265-
/// # Examples
266-
///
267-
/// ```
268-
/// use event_listener::Event;
269-
///
270-
/// let event = Event::new();
271-
/// ```
272-
#[inline]
273-
pub const fn new() -> Event {
274-
Self::with_tag()
275-
}
243+
/// Creates a new [`Event`].
244+
///
245+
/// # Examples
246+
///
247+
/// ```
248+
/// use event_listener::Event;
249+
///
250+
/// let event = Event::new();
251+
/// ```
252+
#[inline]
253+
pub const fn new() -> Event {
254+
Self::with_tag()
276255
}
277256

278257
/// Notifies a number of active listeners without emitting a `SeqCst` fence.
@@ -390,22 +369,19 @@ impl Event {
390369
}
391370

392371
impl<T> Event<T> {
393-
const_fn! {
394-
const_if: #[cfg(not(loom))];
395-
/// Creates a new [`Event`] with a tag.
396-
///
397-
/// # Examples
398-
///
399-
/// ```
400-
/// use event_listener::Event;
401-
///
402-
/// let event = Event::<usize>::with_tag();
403-
/// ```
404-
#[inline]
405-
pub const fn with_tag() -> Event<T> {
406-
Event {
407-
inner: AtomicPtr::new(ptr::null_mut()),
408-
}
372+
/// Creates a new [`Event`] with a tag.
373+
///
374+
/// # Examples
375+
///
376+
/// ```
377+
/// use event_listener::Event;
378+
///
379+
/// let event = Event::<usize>::with_tag();
380+
/// ```
381+
#[inline]
382+
pub const fn with_tag() -> Event<T> {
383+
Event {
384+
inner: AtomicPtr::new(ptr::null_mut()),
409385
}
410386
}
411387

@@ -590,16 +566,13 @@ impl<T> Event<T> {
590566
impl<T> Drop for Event<T> {
591567
#[inline]
592568
fn drop(&mut self) {
593-
loom::ptr_with_mut(&mut self.inner, |inner| {
594-
let inner: *mut Inner<T> = *inner;
595-
596-
// If the state pointer has been initialized, deallocate it.
597-
if !inner.is_null() {
598-
unsafe {
599-
drop(Arc::from_raw(inner));
600-
}
569+
let inner = self.inner.get_mut();
570+
// If the state pointer has been initialized, deallocate it.
571+
if !inner.is_null() {
572+
unsafe {
573+
drop(Arc::from_raw(*inner));
601574
}
602-
});
575+
}
603576
}
604577
}
605578

@@ -835,19 +808,16 @@ fn full_fence() {
835808
// The ideal solution here would be to use inline assembly, but we're instead creating a
836809
// temporary atomic variable and compare-and-exchanging its value. No sane compiler to
837810
// x86 platforms is going to optimize this away.
838-
atomic::compiler_fence(Ordering::SeqCst);
811+
sync::atomic::compiler_fence(Ordering::SeqCst);
839812
let a = AtomicUsize::new(0);
840813
let _ = a.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst);
841-
atomic::compiler_fence(Ordering::SeqCst);
814+
sync::atomic::compiler_fence(Ordering::SeqCst);
842815
} else {
843-
atomic::fence(Ordering::SeqCst);
816+
sync::atomic::fence(Ordering::SeqCst);
844817
}
845818
}
846819

847-
#[cfg(not(loom))]
848-
mod loom {
849-
pub(crate) use core::cell;
850-
820+
pub(crate) mod sync {
851821
#[cfg(not(feature = "portable-atomic"))]
852822
pub(crate) use core::sync::atomic;
853823

@@ -859,32 +829,6 @@ mod loom {
859829

860830
#[cfg(feature = "portable-atomic")]
861831
pub(crate) use portable_atomic_util::Arc;
862-
863-
/// Equivalent to `loom::AtomicPtr::with_mut`
864-
pub(crate) fn ptr_with_mut<T, R>(
865-
ptr: &mut atomic::AtomicPtr<T>,
866-
f: impl FnOnce(&mut *mut T) -> R,
867-
) -> R {
868-
f(ptr.get_mut())
869-
}
870-
}
871-
872-
#[cfg(loom)]
873-
mod loom {
874-
pub(crate) use loom::cell;
875-
pub(crate) use loom::sync::Arc;
876-
877-
pub(crate) mod atomic {
878-
pub(crate) use core::sync::atomic::compiler_fence;
879-
pub(crate) use loom::sync::atomic::*;
880-
}
881-
882-
pub(crate) fn ptr_with_mut<T, R>(
883-
ptr: &mut atomic::AtomicPtr<T>,
884-
f: impl FnOnce(&mut *mut T) -> R,
885-
) -> R {
886-
ptr.with_mut(f)
887-
}
888832
}
889833

890834
mod __sealed {

Diff for: src/linked_list/lock_free.rs

+12-28
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
//! Implementation of the linked list using lock-free primitives.
22
3-
use crate::loom::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
4-
use crate::loom::cell::{Cell, UnsafeCell};
53
use crate::notify::{GenericNotify, Internal, Notification};
6-
7-
#[cfg(not(loom))]
8-
use core::hint::spin_loop;
9-
#[cfg(loom)]
10-
use loom::hint::spin_loop;
11-
4+
use core::cell::{Cell, UnsafeCell};
125
use core::cmp::Reverse;
136
use core::fmt;
7+
use core::hint::spin_loop;
148
use core::iter;
159
use core::marker::PhantomData;
1610
use core::mem::{self, MaybeUninit};
@@ -22,6 +16,8 @@ use core::task::{Context, Poll, Waker};
2216
use alloc::boxed::Box;
2317
use alloc::collections::BinaryHeap;
2418

19+
use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
20+
2521
/// The total number of buckets stored in each thread local.
2622
/// All buckets combined can hold up to `usize::MAX - 1` entries.
2723
const BUCKETS: usize = (usize::BITS - 1) as usize;
@@ -666,16 +662,14 @@ impl<T> Drop for Slots<T> {
666662
fn drop(&mut self) {
667663
// Free every bucket.
668664
for (i, bucket) in self.buckets.iter_mut().enumerate() {
669-
crate::loom::ptr_with_mut(bucket, |bucket| {
670-
let bucket = *bucket;
671-
if bucket.is_null() {
672-
return;
673-
}
665+
let bucket = bucket.get_mut();
666+
if bucket.is_null() {
667+
return;
668+
}
674669

675-
// Drop the bucket.
676-
let size = bucket_index_to_size(i);
677-
drop(unsafe { Box::from_raw(slice::from_raw_parts_mut(bucket, size)) });
678-
});
670+
// Drop the bucket.
671+
let size = bucket_index_to_size(i);
672+
drop(unsafe { Box::from_raw(slice::from_raw_parts_mut(*bucket, size)) });
679673
}
680674
}
681675
}
@@ -743,23 +737,13 @@ impl<T> Lock<T> {
743737
let _drop = CallOnDrop(|| self.is_locked.store(false, Ordering::Release));
744738

745739
// SAFETY: We have exclusive access.
746-
Some(cell_with_mut(&self.data, |ptr| f(unsafe { &mut *ptr })))
740+
Some(f(unsafe { &mut *self.data.get() }))
747741
} else {
748742
None
749743
}
750744
}
751745
}
752746

753-
#[cfg(not(loom))]
754-
fn cell_with_mut<T, R>(cell: &UnsafeCell<T>, f: impl FnOnce(*mut T) -> R) -> R {
755-
f(cell.get())
756-
}
757-
758-
#[cfg(loom)]
759-
fn cell_with_mut<T, R>(cell: &UnsafeCell<T>, f: impl FnOnce(*mut T) -> R) -> R {
760-
cell.with_mut(f)
761-
}
762-
763747
#[inline]
764748
fn bucket_index_to_size(i: usize) -> usize {
765749
1 << i

Diff for: src/linked_list/mutex.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
//! Implementation of the linked list using standard library mutexes.
22
3-
use crate::loom::atomic::{AtomicUsize, Ordering};
4-
use crate::loom::cell::Cell;
53
use crate::notify::{GenericNotify, Internal, Notification};
6-
4+
use crate::sync::atomic::{AtomicUsize, Ordering};
75
use std::boxed::Box;
6+
use std::cell::{Cell, UnsafeCell};
87
use std::fmt;
98
use std::mem;
109
use std::ops::{Deref, DerefMut};
@@ -13,7 +12,6 @@ use std::sync::{Mutex, MutexGuard, TryLockError};
1312
use std::task::{Context, Poll, Waker};
1413
use std::thread::{self, Thread};
1514
use std::time::Instant;
16-
use std::usize;
1715

1816
/// Inner state of [`Event`].
1917
pub(crate) struct Inner<T> {
@@ -26,24 +24,23 @@ pub(crate) struct Inner<T> {
2624
list: Mutex<List<T>>,
2725

2826
/// A single cached list entry to avoid allocations on the fast path of the insertion.
29-
// TODO: Add ability to use loom::cell::UnsafeCell
30-
cache: std::cell::UnsafeCell<Entry<T>>,
27+
cache: UnsafeCell<Entry<T>>,
3128
}
3229

3330
impl<T> Inner<T> {
3431
/// Create a new linked list.
3532
pub(crate) fn new() -> Self {
3633
Inner {
3734
notified: AtomicUsize::new(usize::MAX),
38-
list: std::sync::Mutex::new(List::<T> {
35+
list: Mutex::new(List::<T> {
3936
head: None,
4037
tail: None,
4138
start: None,
4239
len: 0,
4340
notified: 0,
4441
cache_used: false,
4542
}),
46-
cache: std::cell::UnsafeCell::new(Entry {
43+
cache: UnsafeCell::new(Entry {
4744
state: Cell::new(State::Created),
4845
prev: Cell::new(None),
4946
next: Cell::new(None),

Diff for: src/notify.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#[cfg(feature = "std")]
44
use core::fmt;
55

6-
use crate::loom::atomic::{self, Ordering};
6+
use crate::sync::atomic::{self, Ordering};
77

88
pub(crate) use __private::Internal;
99

@@ -568,7 +568,7 @@ impl_for_numeric_types! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
568568
/// Equivalent to `atomic::fence(Ordering::SeqCst)`, but in some cases faster.
569569
#[inline]
570570
pub(super) fn full_fence() {
571-
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri), not(loom)))]
571+
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(miri)))]
572572
{
573573
use core::{arch::asm, cell::UnsafeCell};
574574
// HACK(stjepang): On x86 architectures there are two different ways of executing

0 commit comments

Comments
 (0)