use super::{
ChannelReceiveAccess, ChannelReceiveFuture, ChannelSendError, CloseStatus,
RecvPollState, RecvWaitQueueEntry,
};
use crate::{
intrusive_double_linked_list::{LinkedList, ListNode},
utils::update_waker_ref,
NoopLock,
};
use core::marker::PhantomData;
use futures_core::task::{Context, Poll};
use lock_api::{Mutex, RawMutex};
fn wake_waiters(waiters: &mut LinkedList<RecvWaitQueueEntry>) {
waiters.reverse_drain(|waiter| {
if let Some(handle) = waiter.task.take() {
handle.wake();
}
waiter.state = RecvPollState::Unregistered;
});
}
struct ChannelState<T> {
is_fulfilled: bool,
value: Option<T>,
waiters: LinkedList<RecvWaitQueueEntry>,
}
impl<T> ChannelState<T> {
fn new() -> ChannelState<T> {
ChannelState::<T> {
is_fulfilled: false,
value: None,
waiters: LinkedList::new(),
}
}
fn send(&mut self, value: T) -> Result<(), ChannelSendError<T>> {
if self.is_fulfilled {
return Err(ChannelSendError(value));
}
self.value = Some(value);
self.is_fulfilled = true;
wake_waiters(&mut self.waiters);
Ok(())
}
fn close(&mut self) -> CloseStatus {
if self.is_fulfilled {
return CloseStatus::AlreadyClosed;
}
self.is_fulfilled = true;
wake_waiters(&mut self.waiters);
CloseStatus::NewlyClosed
}
unsafe fn try_receive(
&mut self,
wait_node: &mut ListNode<RecvWaitQueueEntry>,
cx: &mut Context<'_>,
) -> Poll<Option<T>> {
match wait_node.state {
RecvPollState::Unregistered => {
let maybe_val = self.value.take();
match maybe_val {
Some(v) => {
Poll::Ready(Some(v))
}
None => {
if self.is_fulfilled {
Poll::Ready(None)
} else {
wait_node.task = Some(cx.waker().clone());
wait_node.state = RecvPollState::Registered;
self.waiters.add_front(wait_node);
Poll::Pending
}
}
}
}
RecvPollState::Registered => {
update_waker_ref(&mut wait_node.task, cx);
Poll::Pending
}
RecvPollState::Notified => {
unreachable!("Not possible for Oneshot");
}
}
}
fn remove_waiter(&mut self, wait_node: &mut ListNode<RecvWaitQueueEntry>) {
if let RecvPollState::Registered = wait_node.state {
if !unsafe { self.waiters.remove(wait_node) } {
panic!("Future could not be removed from wait queue");
}
wait_node.state = RecvPollState::Unregistered;
}
}
}
pub struct GenericOneshotChannel<MutexType: RawMutex, T> {
inner: Mutex<MutexType, ChannelState<T>>,
}
unsafe impl<MutexType: RawMutex + Send, T: Send> Send
for GenericOneshotChannel<MutexType, T>
{
}
unsafe impl<MutexType: RawMutex + Sync, T: Send> Sync
for GenericOneshotChannel<MutexType, T>
{
}
impl<MutexType: RawMutex, T> core::fmt::Debug
for GenericOneshotChannel<MutexType, T>
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("GenericOneshotChannel").finish()
}
}
impl<MutexType: RawMutex, T> GenericOneshotChannel<MutexType, T> {
pub fn new() -> GenericOneshotChannel<MutexType, T> {
GenericOneshotChannel {
inner: Mutex::new(ChannelState::new()),
}
}
pub fn send(&self, value: T) -> Result<(), ChannelSendError<T>> {
self.inner.lock().send(value)
}
pub fn close(&self) -> CloseStatus {
self.inner.lock().close()
}
pub fn receive(&self) -> ChannelReceiveFuture<MutexType, T> {
ChannelReceiveFuture {
channel: Some(self),
wait_node: ListNode::new(RecvWaitQueueEntry::new()),
_phantom: PhantomData,
}
}
}
impl<MutexType: RawMutex, T> ChannelReceiveAccess<T>
for GenericOneshotChannel<MutexType, T>
{
unsafe fn receive_or_register(
&self,
wait_node: &mut ListNode<RecvWaitQueueEntry>,
cx: &mut Context<'_>,
) -> Poll<Option<T>> {
self.inner.lock().try_receive(wait_node, cx)
}
fn remove_receive_waiter(
&self,
wait_node: &mut ListNode<RecvWaitQueueEntry>,
) {
self.inner.lock().remove_waiter(wait_node)
}
}
pub type LocalOneshotChannel<T> = GenericOneshotChannel<NoopLock, T>;
#[cfg(feature = "std")]
mod if_std {
use super::*;
pub type OneshotChannel<T> =
GenericOneshotChannel<parking_lot::RawMutex, T>;
}
#[cfg(feature = "std")]
pub use self::if_std::*;
#[cfg(feature = "alloc")]
mod if_alloc {
use super::*;
pub mod shared {
use super::*;
use crate::channel::shared::ChannelReceiveFuture;
struct GenericOneshotChannelSharedState<MutexType, T>
where
MutexType: RawMutex,
T: 'static,
{
channel: GenericOneshotChannel<MutexType, T>,
}
impl<MutexType, T> ChannelReceiveAccess<T>
for GenericOneshotChannelSharedState<MutexType, T>
where
MutexType: RawMutex,
{
unsafe fn receive_or_register(
&self,
wait_node: &mut ListNode<RecvWaitQueueEntry>,
cx: &mut Context<'_>,
) -> Poll<Option<T>> {
self.channel.receive_or_register(wait_node, cx)
}
fn remove_receive_waiter(
&self,
wait_node: &mut ListNode<RecvWaitQueueEntry>,
) {
self.channel.remove_receive_waiter(wait_node)
}
}
pub struct GenericOneshotSender<MutexType, T>
where
MutexType: RawMutex,
T: 'static,
{
inner: alloc::sync::Arc<
GenericOneshotChannelSharedState<MutexType, T>,
>,
}
pub struct GenericOneshotReceiver<MutexType, T>
where
MutexType: RawMutex,
T: 'static,
{
inner: alloc::sync::Arc<
GenericOneshotChannelSharedState<MutexType, T>,
>,
}
impl<MutexType, T> core::fmt::Debug for GenericOneshotSender<MutexType, T>
where
MutexType: RawMutex,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("OneshotSender").finish()
}
}
impl<MutexType, T> core::fmt::Debug for GenericOneshotReceiver<MutexType, T>
where
MutexType: RawMutex,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_struct("OneshotReceiver").finish()
}
}
impl<MutexType, T> Drop for GenericOneshotSender<MutexType, T>
where
MutexType: RawMutex,
{
fn drop(&mut self) {
self.inner.channel.close();
}
}
impl<MutexType, T> Drop for GenericOneshotReceiver<MutexType, T>
where
MutexType: RawMutex,
{
fn drop(&mut self) {
self.inner.channel.close();
}
}
pub fn generic_oneshot_channel<MutexType, T>() -> (
GenericOneshotSender<MutexType, T>,
GenericOneshotReceiver<MutexType, T>,
)
where
MutexType: RawMutex,
T: Send,
{
let inner =
alloc::sync::Arc::new(GenericOneshotChannelSharedState {
channel: GenericOneshotChannel::new(),
});
let sender = GenericOneshotSender {
inner: inner.clone(),
};
let receiver = GenericOneshotReceiver { inner };
(sender, receiver)
}
impl<MutexType, T> GenericOneshotSender<MutexType, T>
where
MutexType: RawMutex + 'static,
{
pub fn send(&self, value: T) -> Result<(), ChannelSendError<T>> {
self.inner.channel.send(value)
}
}
impl<MutexType, T> GenericOneshotReceiver<MutexType, T>
where
MutexType: RawMutex + 'static,
{
pub fn receive(&self) -> ChannelReceiveFuture<MutexType, T> {
ChannelReceiveFuture {
channel: Some(self.inner.clone()),
wait_node: ListNode::new(RecvWaitQueueEntry::new()),
_phantom: PhantomData,
}
}
}
#[cfg(feature = "std")]
mod if_std {
use super::*;
pub type OneshotSender<T> =
GenericOneshotSender<parking_lot::RawMutex, T>;
pub type OneshotReceiver<T> =
GenericOneshotReceiver<parking_lot::RawMutex, T>;
pub fn oneshot_channel<T>() -> (OneshotSender<T>, OneshotReceiver<T>)
where
T: Send,
{
generic_oneshot_channel::<parking_lot::RawMutex, T>()
}
}
#[cfg(feature = "std")]
pub use self::if_std::*;
}
}
#[cfg(feature = "alloc")]
pub use self::if_alloc::*;