Revise the poll() method

This commit is contained in:
Ruihan Li 2024-08-31 22:35:40 +08:00 committed by Tate, Hongliang Tian
parent 1469059888
commit 44b55f2ccf

View File

@ -37,27 +37,22 @@ impl Pollee {
} }
} }
/// Returns the current events of the pollee given an event mask. /// Returns the current events of the pollee filtered by the given event mask.
/// ///
/// If no interesting events are polled and a poller is provided, then /// If a poller is provided, the poller will start monitoring the pollee and receive event
/// the poller will start monitoring the pollee and receive event /// notification when the pollee receives interesting events.
/// notification once the pollee gets any interesting events.
/// ///
/// This operation is _atomic_ in the sense that either some interesting /// This operation is _atomic_ in the sense that if there are interesting events, either the
/// events are returned or the poller is registered (if a poller is provided). /// events are returned or the poller is notified.
pub fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents { pub fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents {
let mask = mask | IoEvents::ALWAYS_POLL; let mask = mask | IoEvents::ALWAYS_POLL;
// Fast path: return events immediately // Register the provided poller.
let revents = self.events() & mask; if let Some(poller) = poller {
if !revents.is_empty() || poller.is_none() { self.register_poller(poller, mask);
return revents;
} }
// Register the provided poller. // Check events after the registration to prevent race conditions.
self.register_poller(poller.unwrap(), mask);
// It is important to check events again to handle race conditions
self.events() & mask self.events() & mask
} }
@ -235,8 +230,8 @@ impl Observer<IoEvents> for EventCounter {
/// have access to the internal [`Pollee`], but there is a method that provides the same semantics /// have access to the internal [`Pollee`], but there is a method that provides the same semantics
/// as [`Pollee::poll`] and we need to perform event-based operations using that method. /// as [`Pollee::poll`] and we need to perform event-based operations using that method.
pub trait Pollable { pub trait Pollable {
/// Returns the interesting events if there are any, or waits for them to happen if there are /// Returns the interesting events now and monitors their occurrence in the future if the
/// none. /// poller is provided.
/// ///
/// This method has the same semantics as [`Pollee::poll`]. /// This method has the same semantics as [`Pollee::poll`].
fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents; fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents;
@ -290,9 +285,7 @@ pub trait Pollable {
// Wait until the next event happens. // Wait until the next event happens.
// //
// FIXME: We need to update `timeout` since we have waited for some time. // FIXME: We need to update `timeout` since we have waited for some time.
if self.poll(mask, Some(&mut poller)).is_empty() { poller.wait(timeout)?;
poller.wait(timeout)?;
}
} }
} }
} }