|
71 | 71 | )))] |
72 | 72 | compile_error!("OS not supported"); |
73 | 73 |
|
| 74 | +use std::fmt; |
| 75 | +use std::sync::atomic::{AtomicU8, Ordering}; |
74 | 76 | use std::time::Duration; |
75 | 77 |
|
76 | 78 | // This must come before the other modules for the documentation. |
@@ -506,3 +508,49 @@ impl<T> OpPollResult<T> for Option<io::Result<T>> { |
506 | 508 | None |
507 | 509 | } |
508 | 510 | } |
| 511 | + |
| 512 | +/// Polling state of a [`Ring`]. |
| 513 | +pub(crate) struct PollingState(AtomicU8); |
| 514 | + |
| 515 | +const IS_POLLING: u8 = 0b01; |
| 516 | +#[allow(unused)] // Used in an assert below, but rustc doesn't seem to care. |
| 517 | +const NOT_POLLING: u8 = 0b00; |
| 518 | +const IS_AWOKEN: u8 = 0b10; |
| 519 | +const NOT_AWOKEN: u8 = 0b00; |
| 520 | + |
| 521 | +impl PollingState { |
| 522 | + pub(crate) const fn new() -> PollingState { |
| 523 | + PollingState(AtomicU8::new(0)) |
| 524 | + } |
| 525 | + |
| 526 | + /// Set the state to currently (not) polling. |
| 527 | + /// |
| 528 | + /// Returns a boolean indicating if the poll call should continue like |
| 529 | + /// normal, or should be cut short (e.g. with a zero timeout). |
| 530 | + #[allow(clippy::cast_lossless)] |
| 531 | + pub(crate) fn set_polling(&self, is_polling: bool) -> bool { |
| 532 | + const _BOOL_CAST_CHECK_TRUE: () = assert!(true as u8 == IS_POLLING); |
| 533 | + const _BOOL_CAST_CHECK_FALSE: () = assert!(false as u8 == NOT_POLLING); |
| 534 | + let state = self.0.swap(is_polling as u8 | NOT_AWOKEN, Ordering::AcqRel); |
| 535 | + (state & IS_AWOKEN) != 0 |
| 536 | + } |
| 537 | + |
| 538 | + /// Set the state to wake the polling thread. |
| 539 | + /// |
| 540 | + /// Returns a boolean indicating if the caller should submit an event to |
| 541 | + /// wake up the polling thread. |
| 542 | + pub(crate) fn wake(&self) -> bool { |
| 543 | + let state = self.0.fetch_or(IS_AWOKEN, Ordering::AcqRel); |
| 544 | + state == (IS_POLLING | NOT_AWOKEN) |
| 545 | + } |
| 546 | +} |
| 547 | + |
| 548 | +impl fmt::Debug for PollingState { |
| 549 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 550 | + let state = self.0.load(Ordering::Relaxed); |
| 551 | + f.debug_struct("PollingState") |
| 552 | + .field("polling", &((state & IS_POLLING) != 0)) |
| 553 | + .field("awoken", &((state & IS_AWOKEN) != 0)) |
| 554 | + .finish() |
| 555 | + } |
| 556 | +} |
0 commit comments