| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- use crate::kernel::task::Thread;
- use core::pin::pin;
- use eonix_sync::{UnlockableGuard, UnlockedGuard as _, WaitList};
- use intrusive_collections::UnsafeRef;
- pub struct CondVar<const INTERRUPTIBLE: bool> {
- wait_list: WaitList,
- }
- impl<const I: bool> core::fmt::Debug for CondVar<I> {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- if I {
- f.debug_struct("CondVar").finish()
- } else {
- f.debug_struct("CondVarUnintrruptible").finish()
- }
- }
- }
- impl<const I: bool> CondVar<I> {
- pub const fn new() -> Self {
- Self {
- wait_list: WaitList::new(),
- }
- }
- pub fn notify_all(&self) {
- self.wait_list.notify_all();
- }
- /// Unlock the `guard`. Then wait until being woken up.
- /// Return the relocked `guard`.
- pub async fn wait<G>(&self, guard: G) -> G
- where
- G: UnlockableGuard + Send,
- G::Unlocked: Send,
- {
- let mut wait_handle = pin!(self.wait_list.prepare_to_wait());
- wait_handle.as_mut().add_to_wait_list();
- let interrupt_waker = pin!(unsafe {
- // SAFETY: We won't use the waker after the wait_handle is dropped.
- wait_handle.as_ref().get_waker_function()
- });
- if I {
- // Prohibit the thread from being woken up by a signal.
- Thread::current().signal_list.set_signal_waker(Some(unsafe {
- UnsafeRef::from_raw(interrupt_waker.as_ref().get_ref())
- }));
- }
- let unlocked_guard = guard.unlock();
- wait_handle.await;
- if I {
- // Allow the thread to be woken up by a signal again.
- Thread::current().signal_list.set_signal_waker(None);
- }
- unlocked_guard.relock().await
- }
- }
|