Skip to content

Commit 564b84b

Browse files
authored
m: Remove tag support from no_std
For tagging to work under no-std mode, the tags would need to be stored in the backup queue. For notifications for std::usize::MAX listeners, this is not possible. Therefore the only strategy left to use that doesn't massively constrain the use of tagging is to remove tags from no_std mode. Closes #73 Signed-off-by: John Nunley <[email protected]>
1 parent 1c95cd2 commit 564b84b

File tree

5 files changed

+36
-31
lines changed

5 files changed

+36
-31
lines changed

src/lib.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,23 +176,27 @@ impl<T> fmt::Debug for Event<T> {
176176
}
177177
}
178178

179-
impl<T> Default for Event<T> {
179+
impl Default for Event {
180180
#[inline]
181181
fn default() -> Self {
182-
Self::with_tag()
182+
Self::new()
183183
}
184184
}
185185

186186
impl<T> Event<T> {
187187
/// Creates a new `Event` with a tag type.
188188
///
189+
/// Tagging cannot be implemented efficiently on `no_std`, so this is only available when the
190+
/// `std` feature is enabled.
191+
///
189192
/// # Examples
190193
///
191194
/// ```
192195
/// use event_listener::Event;
193196
///
194197
/// let event = Event::<usize>::with_tag();
195198
/// ```
199+
#[cfg(feature = "std")]
196200
#[inline]
197201
pub const fn with_tag() -> Self {
198202
Self {
@@ -449,7 +453,9 @@ impl Event<()> {
449453
/// ```
450454
#[inline]
451455
pub const fn new() -> Self {
452-
Self::with_tag()
456+
Self {
457+
inner: AtomicPtr::new(ptr::null_mut()),
458+
}
453459
}
454460

455461
/// Notifies a number of active listeners without emitting a `SeqCst` fence.

src/no_std.rs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ mod node;
1515
#[path = "no_std/queue.rs"]
1616
mod queue;
1717

18-
use node::{Node, TaskWaiting};
18+
use node::{Node, NothingProducer, TaskWaiting};
1919
use queue::Queue;
2020

2121
use crate::notify::{GenericNotify, Internal, Notification};
@@ -110,7 +110,7 @@ impl<T> crate::Inner<T> {
110110

111111
/// Notifies a number of entries.
112112
#[cold]
113-
pub(crate) fn notify(&self, mut notify: impl Notification<Tag = T>) -> usize {
113+
pub(crate) fn notify(&self, notify: impl Notification<Tag = T>) -> usize {
114114
match self.try_lock() {
115115
Some(mut guard) => {
116116
// Notify the listeners.
@@ -122,21 +122,7 @@ impl<T> crate::Inner<T> {
122122
let node = Node::Notify(GenericNotify::new(
123123
notify.count(Internal::new()),
124124
notify.is_additional(Internal::new()),
125-
{
126-
// Collect every tag we need.
127-
let tags = {
128-
let count = notify.count(Internal::new());
129-
let mut tags = Vec::with_capacity(count);
130-
for _ in 0..count {
131-
tags.push(notify.next_tag(Internal::new()));
132-
}
133-
134-
// Convert into an iterator.
135-
tags.into_iter()
136-
};
137-
138-
node::VecProducer(tags)
139-
},
125+
NothingProducer::default(),
140126
));
141127

142128
self.list.queue.push(node);

src/no_std/node.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,30 @@ use crate::sys::ListenerSlab;
99
use crate::{State, Task};
1010

1111
use alloc::boxed::Box;
12-
use alloc::vec::IntoIter as VecIter;
1312

13+
use core::marker::PhantomData;
14+
use core::mem;
1415
use core::num::NonZeroUsize;
1516
use core::ptr;
1617

17-
pub(crate) struct VecProducer<T>(pub(crate) VecIter<T>);
18+
pub(crate) struct NothingProducer<T>(PhantomData<T>);
1819

19-
impl<T> TagProducer for VecProducer<T> {
20+
impl<T> Default for NothingProducer<T> {
21+
fn default() -> Self {
22+
Self(PhantomData)
23+
}
24+
}
25+
26+
impl<T> TagProducer for NothingProducer<T> {
2027
type Tag = T;
2128

2229
fn next_tag(&mut self) -> Self::Tag {
23-
self.0.next().unwrap()
30+
// This has to be a zero-sized type with no drop handler.
31+
assert_eq!(mem::size_of::<Self::Tag>(), 0);
32+
assert!(!mem::needs_drop::<Self::Tag>());
33+
34+
// SAFETY: As this is a ZST without a drop handler, zero is valid.
35+
unsafe { mem::zeroed() }
2436
}
2537
}
2638

@@ -35,7 +47,7 @@ pub(crate) enum Node<T> {
3547
},
3648

3749
/// This node is notifying a listener.
38-
Notify(GenericNotify<VecProducer<T>>),
50+
Notify(GenericNotify<NothingProducer<T>>),
3951

4052
/// This node is removing a listener.
4153
RemoveListener {

src/no_std/queue.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,12 @@ impl<T> Drop for Queue<T> {
131131
#[cfg(test)]
132132
mod tests {
133133
use crate::notify::{GenericNotify, Internal, NotificationPrivate};
134-
use crate::sys::node::VecProducer;
134+
use crate::sys::node::NothingProducer;
135135

136136
use super::*;
137137

138138
fn node_from_num(num: usize) -> Node<()> {
139-
Node::Notify(GenericNotify::new(
140-
num,
141-
true,
142-
VecProducer(vec![(); num].into_iter()),
143-
))
139+
Node::Notify(GenericNotify::new(num, true, NothingProducer::default()))
144140
}
145141

146142
fn node_to_num(node: Node<()>) -> usize {

src/notify.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ impl<N: fmt::Debug, F> fmt::Debug for TagWith<N, F> {
222222

223223
impl<N, F> TagWith<N, F> {
224224
/// Create a new `TagFn` with the given tag function and notification.
225+
#[cfg(feature = "std")]
225226
fn new(tag: F, inner: N) -> Self {
226227
Self { tag, inner }
227228
}
@@ -494,6 +495,9 @@ pub trait IntoNotification: __private::Sealed {
494495
/// it is possible to optimize a `Mutex` implementation by locking directly on the next listener, without
495496
/// needing to ever unlock the mutex at all.
496497
///
498+
/// Tagging functions cannot be implemented efficiently for `no_std`, so this is only available
499+
/// when the `std` feature is enabled.
500+
///
497501
/// # Examples
498502
///
499503
/// ```
@@ -511,6 +515,7 @@ pub trait IntoNotification: __private::Sealed {
511515
/// assert_eq!(listener1.as_mut().wait(), true);
512516
/// assert_eq!(listener2.as_mut().wait(), false);
513517
/// ```
518+
#[cfg(feature = "std")]
514519
fn tag_with<T, F>(self, tag: F) -> TagWith<Self::Notify, F>
515520
where
516521
Self: Sized + IntoNotification<Tag = ()>,

0 commit comments

Comments
 (0)