Rename reactor -> driver, prep for lib/reactivity

This commit is contained in:
2026-03-19 19:47:06 -04:00
parent 3fd8209420
commit 7b3c2fcbef
13 changed files with 490 additions and 62 deletions

View File

@@ -1,3 +1,5 @@
//! Single-use channels for handing one value from a sender to a receiver.
use std::future::poll_fn;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
@@ -6,6 +8,15 @@ use std::task::{Context, Poll};
use crate::op::completion::{CompletionFuture, CompletionHandle};
use crate::sys::linux::channel::runtime_waiter;
/// Creates a single-use channel for transferring one value from a [`Sender`] to a [`Receiver`].
///
/// # Examples
///
/// ```
/// let (sender, mut receiver) = ruin_runtime::channel::oneshot::channel::<usize>();
/// sender.send(7).unwrap();
/// assert_eq!(receiver.try_recv(), Ok(7));
/// ```
pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
let shared = Arc::new(Mutex::new(State {
value: None,
@@ -24,10 +35,12 @@ pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
)
}
/// Sending half of a oneshot channel.
pub struct Sender<T: Send + 'static> {
shared: Option<Arc<Mutex<State<T>>>>,
}
/// Receiving half of a oneshot channel.
pub struct Receiver<T: Send + 'static> {
shared: Arc<Mutex<State<T>>>,
consumed: bool,
@@ -41,18 +54,27 @@ struct State<T: Send + 'static> {
}
#[derive(Debug, Eq, PartialEq)]
/// Error returned when a oneshot send fails because the receiver is gone or closed.
pub struct SendError<T>(pub T);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// Error returned when a oneshot receive observes a closed channel with no value.
pub struct RecvError;
#[derive(Debug, Eq, PartialEq)]
/// Non-blocking receive errors for [`Receiver::try_recv`].
pub enum TryRecvError {
/// No value has been sent yet, and the sender is still alive.
Empty,
/// The channel can never yield a value.
Closed,
}
impl<T: Send + 'static> Sender<T> {
/// Sends `value` into the channel.
///
/// This consumes the sender. If the receiver is already waiting on a runtime thread, the
/// receive future is woken through the runtime's cross-thread notifier path.
pub fn send(mut self, value: T) -> Result<(), SendError<T>> {
let Some(shared) = self.shared.take() else {
return Err(SendError(value));
@@ -80,6 +102,7 @@ impl<T: Send + 'static> Sender<T> {
Ok(())
}
/// Returns `true` if the receiver has been closed or dropped.
pub fn is_closed(&self) -> bool {
self.shared.as_ref().is_none_or(|shared| {
shared
@@ -91,11 +114,19 @@ impl<T: Send + 'static> Sender<T> {
}
impl<T: Send + 'static> Receiver<T> {
/// Waits for the channel's value.
///
/// # Panics
///
/// Panics if this future is first polled outside a runtime-managed thread. Async channel
/// waiting registers with the current runtime thread so it can be woken through the driver's
/// notification path.
pub async fn recv(&mut self) -> Result<T, RecvError> {
let mut wait = None;
poll_fn(|cx| self.poll_recv(cx, &mut wait)).await
}
/// Attempts to receive the value without waiting.
pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
if self.consumed {
return Err(TryRecvError::Closed);
@@ -118,6 +149,10 @@ impl<T: Send + 'static> Receiver<T> {
}
}
/// Closes the receiver.
///
/// Closing prevents future sends from succeeding. If a value has already been sent, it can
/// still be retrieved.
pub fn close(&mut self) {
let mut state = self
.shared
@@ -126,6 +161,7 @@ impl<T: Send + 'static> Receiver<T> {
state.receiver_closed = true;
}
/// Returns `true` if the channel is closed to future sends.
pub fn is_closed(&self) -> bool {
let state = self
.shared