Skip to content

Commit 85e3474

Browse files
committed
bugfix: Disable early-out notify optimization
The notify() function contains two optimizations: - If the `inner` field is not yet initialized (i.e. no listeners have been created yet), it returns `0` from the function early. - If the atomic `notified` field indicates that the current notification would do nothing, it returns `0` early as well. `loom` testing has exposed race conditions in these optimizations that can cause notifications to be missed, leading to deadlocks. This commit removes these optimizations in the hope of preventing these deadlocks. Ideally we can restore them in the future. Closes #138 cc #130 and #133 Signed-off-by: John Nunley <[email protected]>
1 parent fdbe437 commit 85e3474

File tree

3 files changed

+3
-26
lines changed

3 files changed

+3
-26
lines changed

Diff for: src/lib.rs

+3-16
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ use sync::Arc;
111111
#[cfg(not(loom))]
112112
use sync::WithMut;
113113

114-
use notify::{Internal, NotificationPrivate};
114+
use notify::NotificationPrivate;
115115
pub use notify::{IntoNotification, Notification};
116116

117117
/// Inner state of [`Event`].
@@ -437,21 +437,8 @@ impl<T> Event<T> {
437437
// Make sure the notification comes after whatever triggered it.
438438
notify.fence(notify::Internal::new());
439439

440-
if let Some(inner) = self.try_inner() {
441-
let limit = if notify.is_additional(Internal::new()) {
442-
usize::MAX
443-
} else {
444-
notify.count(Internal::new())
445-
};
446-
447-
// Notify if there is at least one unnotified listener and the number of notified
448-
// listeners is less than `limit`.
449-
if inner.needs_notification(limit) {
450-
return inner.notify(notify);
451-
}
452-
}
453-
454-
0
440+
let inner = unsafe { &*self.inner() };
441+
inner.notify(notify)
455442
}
456443

457444
/// Return a reference to the inner state if it has been initialized.

Diff for: src/no_std.rs

-5
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ impl<T> crate::Inner<T> {
4545
drop(self.try_lock());
4646
}
4747

48-
pub(crate) fn needs_notification(&self, _limit: usize) -> bool {
49-
// TODO: Figure out a stable way to do this optimization.
50-
true
51-
}
52-
5348
/// Add a new listener to the list.
5449
///
5550
/// Does nothing if the list is already registered.

Diff for: src/std.rs

-5
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ impl<T> crate::Inner<T> {
6464
}
6565
}
6666

67-
/// Whether or not this number of listeners would lead to a notification.
68-
pub(crate) fn needs_notification(&self, limit: usize) -> bool {
69-
self.notified.load(Ordering::Acquire) < limit
70-
}
71-
7267
/// Add a new listener to the list.
7368
pub(crate) fn insert(&self, mut listener: Pin<&mut Option<Listener<T>>>) {
7469
let mut inner = self.lock();

0 commit comments

Comments
 (0)