//! An asynchronously awaitable multi producer multi consumer channel use crate::intrusive_double_linked_list::{LinkedList, ListNode}; use crate::{ buffer::{ArrayBuf, RingBuf}, utils::update_waker_ref, NoopLock, }; use core::{marker::PhantomData, pin::Pin}; use futures_core::{ future::Future, stream::{FusedStream, Stream}, task::{Context, Poll, Waker}, }; use lock_api::{Mutex, RawMutex}; use super::{ ChannelReceiveAccess, ChannelReceiveFuture, ChannelSendAccess, ChannelSendFuture, CloseStatus, RecvPollState, RecvWaitQueueEntry, SendPollState, SendWaitQueueEntry, TryReceiveError, TrySendError, }; fn wake_recv_waiters(waiters: &mut LinkedList) { // Remove all waiters from the waiting list in reverse order and wake them. // We reverse the waiter list, so that the oldest waker (which is // at the end of the list), gets woken first and has the best // chance to grab the channel value. waiters.reverse_drain(|waiter| { if let Some(handle) = waiter.task.take() { handle.wake(); } // The only kind of waiter that could have been stored here are // registered waiters (with a value), since others are removed // whenever their value had been copied into the channel. waiter.state = RecvPollState::Unregistered; }); } fn wake_send_waiters(waiters: &mut LinkedList>) { // Remove all waiters from the waiting list in reverse order and wake them. // We reverse the waiter list, so that the oldest waker (which is // at the end of the list), gets woken first and has the best // chance to send. waiters.reverse_drain(|waiter| { if let Some(handle) = waiter.task.take() { handle.wake(); } waiter.state = SendPollState::Unregistered; }); } /// Wakes up the last waiter and removes it from the wait queue #[must_use] fn return_oldest_receive_waiter( waiters: &mut LinkedList, ) -> Option { let last_waiter = waiters.remove_last(); if let Some(last_waiter) = last_waiter { last_waiter.state = RecvPollState::Notified; last_waiter.task.take() } else { None } } /// Internal state of the channel struct ChannelState where A: RingBuf, { /// Whether the channel had been closed is_closed: bool, /// The value which is stored inside the channel buffer: A, /// Futures which are waiting on receive receive_waiters: LinkedList, /// Futures which are waiting on send send_waiters: LinkedList>, } impl ChannelState where A: RingBuf, { fn new(buffer: A) -> ChannelState { ChannelState:: { is_closed: false, buffer, receive_waiters: LinkedList::new(), send_waiters: LinkedList::new(), } } fn clear(&mut self) { while !self.buffer.is_empty() { self.buffer.pop(); } } fn close(&mut self) -> CloseStatus { if self.is_closed { return CloseStatus::AlreadyClosed; } self.is_closed = true; // Wakeup all send and receive waiters, since they are now guaranteed // to make progress. wake_recv_waiters(&mut self.receive_waiters); wake_send_waiters(&mut self.send_waiters); CloseStatus::NewlyClosed } /// Attempt to send a value without waiting. /// Returns a `Waker` if sending the value lead enabled a task to run. fn try_send(&mut self, value: T) -> Result, TrySendError> { debug_assert!( self.buffer.capacity() > 0, "try_send is not supported for unbuffered channels" ); if self.is_closed { Err(TrySendError::Closed(value)) } else if self.buffer.can_push() { self.buffer.push(value); // Return the oldest receive waiter Ok(return_oldest_receive_waiter(&mut self.receive_waiters)) } else { Err(TrySendError::Full(value)) } } /// Tries to send a value to the channel. /// If the value isn't available yet, the ChannelSendFuture gets added to the /// wait queue at the channel, and will be signalled once ready. /// If the channels is already closed, the value to send is returned. /// This function is only safe as long as the `wait_node`s address is guaranteed /// to be stable until it gets removed from the queue. /// If sending the value succeeded, the `Waker` for a task which can receive /// the value is returned. unsafe fn send_or_register( &mut self, wait_node: &mut ListNode>, cx: &mut Context<'_>, ) -> (Poll<()>, Option, Option) { match wait_node.state { SendPollState::Unregistered => { if self.is_closed { let value = wait_node.value.take(); return (Poll::Ready(()), value, None); } if !self.buffer.can_push() { // If the capacity is exhausted, register a waiter wait_node.task = Some(cx.waker().clone()); wait_node.state = SendPollState::Registered; self.send_waiters.add_front(wait_node); // Return the oldest receive waiter let waker = return_oldest_receive_waiter(&mut self.receive_waiters); return (Poll::Pending, None, waker); } else { // Otherwise copy the value directly into the channel let value = wait_node .value .take() .expect("wait_node must contain value"); self.buffer.push(value); // Return the oldest receive waiter let waker = return_oldest_receive_waiter(&mut self.receive_waiters); (Poll::Ready(()), None, waker) } } SendPollState::Registered => { // Since the channel wakes up all waiters and moves their states // to unregistered there can't be space available in the channel. // However the caller might have passed a different `Waker`. // In this case we need to update it. update_waker_ref(&mut wait_node.task, cx); (Poll::Pending, None, None) } SendPollState::SendComplete => { // The transfer is complete, and the sender has already been removed from the // list of pending senders (Poll::Ready(()), None, None) } } } /// If there is a send waiter, copy it's value into the channel buffer and complete it. /// The method may only be called if there is space in the receive buffer. #[must_use] fn try_copy_value_from_oldest_waiter(&mut self) -> Option { let last_waiter = self.send_waiters.remove_last(); if let Some(last_waiter) = last_waiter { let value = last_waiter .value .take() .expect("wait_node must contain value"); self.buffer.push(value); last_waiter.state = SendPollState::SendComplete; last_waiter.task.take() } else { None } } /// Tries to extract a value from the sending waiter which has been waiting /// longest on the send operation to complete. fn try_take_value_from_sender(&mut self) -> Option<(T, Option)> { // Safety: The method is only called inside the lock on a consistent // list. match self.send_waiters.remove_last() { Some(last_sender) => { // This path should be only used for 0 capacity queues. // Since the list is not empty, a value is available. // Extract it from the sender in order to return it debug_assert_eq!(0, self.buffer.capacity()); // Safety: The sender can't be invalid, since we only add valid // senders to the queue let val = last_sender.value.take().expect("Value must be available"); last_sender.state = SendPollState::SendComplete; // Return the waiter Some((val, last_sender.task.take())) } None => None, } } /// Tries to receive a value from the channel without waiting. fn try_receive(&mut self) -> Result<(T, Option), TryReceiveError> { if !self.buffer.is_empty() { let val = self.buffer.pop(); // Since this means a space in the buffer had been freed, // try to copy a value from a potential waiter into the channel. let waker = self.try_copy_value_from_oldest_waiter(); Ok((val, waker)) } else if let Some((val, waker)) = self.try_take_value_from_sender() { Ok((val, waker)) } else if self.is_closed { Err(TryReceiveError::Closed) } else { Err(TryReceiveError::Empty) } } /// Tries to read the value from the channel. /// If the value isn't available yet, the ChannelReceiveFuture gets added to the /// wait queue at the channel, and will be signalled once ready. /// This function is only safe as long as the `wait_node`s address is guaranteed /// to be stable until it gets removed from the queue. unsafe fn receive_or_register( &mut self, wait_node: &mut ListNode, cx: &mut Context<'_>, ) -> Poll)>> { match wait_node.state { RecvPollState::Unregistered | RecvPollState::Notified => { wait_node.state = RecvPollState::Unregistered; match self.try_receive() { Ok(val) => Poll::Ready(Some(val)), Err(TryReceiveError::Closed) => Poll::Ready(None), Err(TryReceiveError::Empty) => { // Added the task to the wait queue wait_node.task = Some(cx.waker().clone()); wait_node.state = RecvPollState::Registered; self.receive_waiters.add_front(wait_node); Poll::Pending } } } RecvPollState::Registered => { // Since the channel wakes up all waiters and moves their states // to unregistered there can't be any value in the channel in // this state. However the caller might have passed a different `Waker`. // In this case we need to update it. update_waker_ref(&mut wait_node.task, cx); Poll::Pending } } } fn remove_send_waiter( &mut self, wait_node: &mut ListNode>, ) { // ChannelSendFuture only needs to get removed if it had been added to // the wait queue of the channel. // This has happened in the SendPollState::Registered case. match wait_node.state { SendPollState::Registered => { // Safety: Due to the state, we know that the node must be part // of the waiter list if !unsafe { self.send_waiters.remove(wait_node) } { // Panic if the address isn't found. This can only happen if the contract was // violated, e.g. the WaitQueueEntry got moved after the initial poll. panic!("Future could not be removed from wait queue"); } wait_node.state = SendPollState::Unregistered; } SendPollState::Unregistered => {} SendPollState::SendComplete => { // Send was complete. In that case the queue item is not in the list } } } #[must_use] fn remove_receive_waiter( &mut self, wait_node: &mut ListNode, ) -> Option { // ChannelReceiveFuture only needs to get removed if it had been added to // the wait queue of the channel. This has happened in the RecvPollState::Registered case. match wait_node.state { RecvPollState::Registered => { // Safety: Due to the state, we know that the node must be part // of the waiter list if !unsafe { self.receive_waiters.remove(wait_node) } { // Panic if the address isn't found. This can only happen if the contract was // violated, e.g. the WaitQueueEntry got moved after the initial poll. panic!("Future could not be removed from wait queue"); } wait_node.state = RecvPollState::Unregistered; None } RecvPollState::Notified => { // wakeup another receive waiter instead wait_node.state = RecvPollState::Unregistered; return_oldest_receive_waiter(&mut self.receive_waiters) } RecvPollState::Unregistered => None, } } } /// A channel which can be used to exchange values of type `T` between /// concurrent tasks. /// /// `A` represents the backing buffer for a Channel. E.g. a channel which /// can buffer up to 4 `i32` values can be created via: /// /// ``` /// # use futures_intrusive::channel::LocalChannel; /// let channel: LocalChannel = LocalChannel::new(); /// ``` /// /// Tasks can receive values from the channel through the `receive` method. /// The returned Future will get resolved when a value is sent into the channel. /// Values can be sent into the channel through `send`. /// The returned Future will get resolved when the value has been stored /// inside the channel. pub struct GenericChannel where A: RingBuf, { inner: Mutex>, } // The channel can be sent to other threads as long as it's not borrowed and the // value in it can be sent to other threads. unsafe impl Send for GenericChannel where A: RingBuf + Send, { } // The channel is thread-safe as long as a thread-safe mutex is used unsafe impl Sync for GenericChannel where A: RingBuf, { } impl core::fmt::Debug for GenericChannel where A: RingBuf, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("Channel").finish() } } impl GenericChannel where A: RingBuf, { /// Creates a new Channel, utilizing the default capacity that /// the RingBuffer in `A` provides. pub fn new() -> Self { GenericChannel { inner: Mutex::new(ChannelState::new(A::new())), } } /// Creates a new Channel, which has storage for a `capacity` items. /// Depending on the utilized `RingBuf` type, the capacity argument might /// be ignored and the default capacity might be utilized. pub fn with_capacity(capacity: usize) -> Self { GenericChannel { inner: Mutex::new(ChannelState::new(A::with_capacity(capacity))), } } /// Returns a future that gets fulfilled when the value has been written to /// the channel. /// If the channel gets closed while the send is in progress, sending the /// value will fail, and the future will deliver the value back. pub fn send(&self, value: T) -> ChannelSendFuture { ChannelSendFuture { channel: Some(self), wait_node: ListNode::new(SendWaitQueueEntry::new(value)), _phantom: PhantomData, } } /// Attempt to send the value without waiting. /// /// This operation is not supported for unbuffered channels and will /// panic if the capacity of the `RingBuf` is zero. The reason for this is /// that the actual value transfer on unbuffered channels always happens /// when a receiving task copies the value out of the sending task while it /// is waiting. If the sending task does not wait, the value can not be /// transferred. Since this method can therefore never yield a reasonable /// result with unbuffered channels, it panics in order to highlight the /// use of an inappropriate API. pub fn try_send(&self, value: T) -> Result<(), TrySendError> { let result = { self.inner.lock().try_send(value) }; match result { Ok(Some(waker)) => { waker.wake(); Ok(()) } Ok(None) => Ok(()), Err(e) => Err(e), } } /// Returns a future that gets fulfilled when a value is written to the channel. /// If the channels gets closed, the future will resolve to `None`. pub fn receive(&self) -> ChannelReceiveFuture { ChannelReceiveFuture { channel: Some(self), wait_node: ListNode::new(RecvWaitQueueEntry::new()), _phantom: PhantomData, } } /// Attempt to receive a value of the channel without waiting. pub fn try_receive(&self) -> Result { let result = { self.inner.lock().try_receive() }; match result { Ok((val, waker)) => { if let Some(waker) = waker { waker.wake(); } Ok(val) } Err(e) => Err(e), } } /// Returns a stream that will receive values from this channel. /// /// This stream does not yield `None` when the channel is empty, /// instead it yields `None` when it is terminated. pub fn stream(&self) -> ChannelStream { ChannelStream { channel: Some(self), future: None, } } /// Closes the channel. /// All pending and future send attempts will fail. /// Receive attempts will continue to succeed as long as there are items /// stored inside the channel. Further attempts will fail. pub fn close(&self) -> CloseStatus { self.inner.lock().close() } } impl ChannelSendAccess for GenericChannel where A: RingBuf, { unsafe fn send_or_register( &self, wait_node: &mut ListNode>, cx: &mut Context<'_>, ) -> (Poll<()>, Option) { let (poll_result, value, waker) = { self.inner.lock().send_or_register(wait_node, cx) }; if let Some(waker) = waker { waker.wake(); } (poll_result, value) } fn remove_send_waiter( &self, wait_node: &mut ListNode>, ) { self.inner.lock().remove_send_waiter(wait_node) } } impl ChannelReceiveAccess for GenericChannel where A: RingBuf, { unsafe fn receive_or_register( &self, wait_node: &mut ListNode, cx: &mut Context<'_>, ) -> Poll> { let result = { self.inner.lock().receive_or_register(wait_node, cx) }; match result { Poll::Ready(Some((val, waker))) => { if let Some(waker) = waker { waker.wake(); } Poll::Ready(Some(val)) } Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending, } } fn remove_receive_waiter( &self, wait_node: &mut ListNode, ) { let waker = { self.inner.lock().remove_receive_waiter(wait_node) }; if let Some(waker) = waker { waker.wake(); } } } /// A stream that receives from a `GenericChannel`. /// /// Not driving the `ChannelStream` to completion after it has been polled /// might lead to lost wakeup notifications. #[derive(Debug)] pub struct ChannelStream<'a, MutexType: RawMutex, T, A> where A: RingBuf, { channel: Option<&'a GenericChannel>, future: Option>, } impl<'a, MutexType, T, A> Stream for ChannelStream<'a, MutexType, T, A> where A: RingBuf, MutexType: RawMutex, { type Item = T; fn poll_next( self: Pin<&mut Self>, cx: &mut Context, ) -> Poll> { // It might be possible to use Pin::map_unchecked here instead of the two unsafe APIs. // However this didn't seem to work for some borrow checker reasons // Safety: The next operations are safe, because Pin promises us that // the address of the wait queue entry inside ChannelReceiveFuture is stable, // and we don't move any fields inside the future until it gets dropped. let mut_self: &mut Self = unsafe { Pin::get_unchecked_mut(self) }; match mut_self.channel.take() { Some(channel) => { // Poll the next element. if mut_self.future.is_none() { mut_self.future.replace(channel.receive()); } let fut = mut_self.future.as_mut().unwrap(); // Safety: We guarantee that the pinned future will not move until // it resolves by storing it as part of the pinned `Stream` let poll = unsafe { let pin_fut = Pin::new_unchecked(fut); pin_fut.poll(cx) }; // Future was resolved, drop it. if poll.is_ready() { mut_self.future.take(); // If the channel was terminated, we let it drop. if let Poll::Ready(None) = &poll { return poll; } } // The channel was not terminated, so we reuse it. mut_self.channel.replace(channel); poll } // Channel was terminated. None => Poll::Ready(None), } } } impl<'a, MutexType, T, A> FusedStream for ChannelStream<'a, MutexType, T, A> where A: RingBuf, MutexType: RawMutex, { fn is_terminated(&self) -> bool { self.channel.is_none() } } // Export a non thread-safe version using NoopLock /// A [`GenericChannel`] implementation which is not thread-safe. pub type LocalChannel = GenericChannel>; /// An unbuffered [`GenericChannel`] implementation which is not thread-safe. pub type LocalUnbufferedChannel = LocalChannel; #[cfg(feature = "std")] mod if_std { use super::*; // Export a thread-safe version using parking_lot::RawMutex // TODO: We might also want to bind Channel to GenericChannel<..., FixedHeapBuf>, // which performs less type-churn. // However since we can't bind LocalChannel to that too due to no-std compatibility, // this would to introduce some inconsistency between those types. // It's also bit unfortunate that there are now `new()` and `with_capacity` // methods on both types, but for the array backed implementation only // `new()` is meaningful, while for the heap backed implementation only // `with_capacity()` is meaningful. /// A [`GenericChannel`] implementation backed by [`parking_lot`]. pub type Channel = GenericChannel>; /// An unbuffered [`GenericChannel`] implementation backed by [`parking_lot`]. pub type UnbufferedChannel = Channel; } #[cfg(feature = "std")] pub use self::if_std::*; #[cfg(feature = "alloc")] mod if_alloc { use super::*; /// Channel implementations where Sender and Receiver sides are cloneable /// and owned. /// The Futures produced by channels in this module don't require a lifetime /// parameter. pub mod shared { use super::*; use crate::channel::shared::{ChannelReceiveFuture, ChannelSendFuture}; use core::sync::atomic::{AtomicUsize, Ordering}; /// Shared Channel State, which is referenced by Senders and Receivers struct GenericChannelSharedState where MutexType: RawMutex, T: 'static, A: RingBuf, { /// The amount of [`GenericSender`] instances which reference this state. senders: AtomicUsize, /// The amount of [`GenericReceiver`] instances which reference this state. receivers: AtomicUsize, /// The channel on which is acted. channel: GenericChannel, } // Implement ChannelAccess trait for SharedChannelState, so that it can // be used for dynamic dispatch in futures. impl ChannelReceiveAccess for GenericChannelSharedState where MutexType: RawMutex, A: RingBuf, { unsafe fn receive_or_register( &self, wait_node: &mut ListNode, cx: &mut Context<'_>, ) -> Poll> { self.channel.receive_or_register(wait_node, cx) } fn remove_receive_waiter( &self, wait_node: &mut ListNode, ) { self.channel.remove_receive_waiter(wait_node) } } // Implement ChannelAccess trait for SharedChannelState, so that it can // be used for dynamic dispatch in futures. impl ChannelSendAccess for GenericChannelSharedState where MutexType: RawMutex, A: RingBuf, { unsafe fn send_or_register( &self, wait_node: &mut ListNode>, cx: &mut Context<'_>, ) -> (Poll<()>, Option) { self.channel.send_or_register(wait_node, cx) } fn remove_send_waiter( &self, wait_node: &mut ListNode>, ) { self.channel.remove_send_waiter(wait_node) } } /// The sending side of a channel which can be used to exchange values /// between concurrent tasks. /// /// Values can be sent into the channel through `send`. /// The returned Future will get resolved when the value has been stored inside the channel. pub struct GenericSender where MutexType: RawMutex, A: RingBuf, T: 'static, { inner: alloc::sync::Arc>, } /// The receiving side of a channel which can be used to exchange values /// between concurrent tasks. /// /// Tasks can receive values from the channel through the `receive` method. /// The returned Future will get resolved when a value is sent into the channel. pub struct GenericReceiver where MutexType: RawMutex, A: RingBuf, T: 'static, { inner: alloc::sync::Arc>, } impl core::fmt::Debug for GenericSender where MutexType: RawMutex, A: RingBuf, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("Sender").finish() } } impl core::fmt::Debug for GenericReceiver where MutexType: RawMutex, A: RingBuf, { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { f.debug_struct("Receiver").finish() } } impl Clone for GenericSender where MutexType: RawMutex, A: RingBuf, { fn clone(&self) -> Self { let old_size = self.inner.senders.fetch_add(1, Ordering::Relaxed); if old_size > (core::isize::MAX) as usize { panic!("Reached maximum refcount"); } GenericSender { inner: self.inner.clone(), } } } impl Drop for GenericSender where MutexType: RawMutex, A: RingBuf, { fn drop(&mut self) { if self.inner.senders.fetch_sub(1, Ordering::Release) != 1 { return; } core::sync::atomic::fence(Ordering::Acquire); // Close the channel, before last sender gets destroyed // TODO: We could potentially avoid this, if no receiver is left self.inner.channel.close(); } } impl Clone for GenericReceiver where MutexType: RawMutex, A: RingBuf, { fn clone(&self) -> Self { let old_size = self.inner.receivers.fetch_add(1, Ordering::Relaxed); if old_size > (core::isize::MAX) as usize { panic!("Reached maximum refcount"); } GenericReceiver { inner: self.inner.clone(), } } } impl Drop for GenericReceiver where MutexType: RawMutex, A: RingBuf, { fn drop(&mut self) { if self.inner.receivers.fetch_sub(1, Ordering::Release) != 1 { return; } core::sync::atomic::fence(Ordering::Acquire); // Close the channel, before last receiver gets destroyed // TODO: We could potentially avoid this, if no sender is left self.inner.channel.close(); // Now drop the content of the channel. This ensures that // the content of the channel is dropped even if a sender is held. self.inner.channel.inner.lock().clear(); } } /// Creates a new Channel which can be used to exchange values of type `T` between /// concurrent tasks. The ends of the Channel are represented through /// the returned Sender and Receiver. /// Both the Sender and Receiver can be cloned in order to let more tasks /// interact with the Channel. /// /// As soon es either all Senders or all Receivers are closed, the Channel /// itself will be closed. /// /// The channel can buffer up to `capacity` items internally. pub fn generic_channel( capacity: usize, ) -> ( GenericSender, GenericReceiver, ) where MutexType: RawMutex, A: RingBuf, T: Send, { let inner = alloc::sync::Arc::new(GenericChannelSharedState { channel: GenericChannel::with_capacity(capacity), senders: AtomicUsize::new(1), receivers: AtomicUsize::new(1), }); let sender = GenericSender { inner: inner.clone(), }; let receiver = GenericReceiver { inner }; (sender, receiver) } impl GenericSender where MutexType: 'static + RawMutex, A: 'static + RingBuf, { /// Returns a future that gets fulfilled when the value has been written to /// the channel. /// If the channel gets closed while the send is in progress, sending the /// value will fail, and the future will deliver the value back. pub fn send(&self, value: T) -> ChannelSendFuture { ChannelSendFuture { channel: Some(self.inner.clone()), wait_node: ListNode::new(SendWaitQueueEntry::new(value)), _phantom: PhantomData, } } /// Attempt to send the value without waiting. /// /// This operation is not supported for unbuffered channels and will /// panic if the capacity of the `RingBuf` is zero. The reason for this is /// that the actual value transfer on unbuffered channels always happens /// when a receiving task copies the value out of the sending task while it /// is waiting. If the sending task does not wait, the value can not be /// transferred. Since this method can therefore never yield a reasonable /// result with unbuffered channels, it panics in order to highlight the /// use of an inappropriate API. pub fn try_send(&self, value: T) -> Result<(), TrySendError> { self.inner.channel.try_send(value) } /// Closes the channel. /// All pending future send attempts will fail. /// Receive attempts will continue to succeed as long as there are items /// stored inside the channel. Further attempts will return `None`. pub fn close(&self) -> CloseStatus { self.inner.channel.close() } } impl GenericReceiver where MutexType: 'static + RawMutex, A: 'static + RingBuf, { /// Returns a future that gets fulfilled when a value is written to the channel. /// If the channels gets closed, the future will resolve to `None`. pub fn receive(&self) -> ChannelReceiveFuture { ChannelReceiveFuture { channel: Some(self.inner.clone()), wait_node: ListNode::new(RecvWaitQueueEntry::new()), _phantom: PhantomData, } } /// Attempt to receive form the channel without waiting. pub fn try_receive(&self) -> Result { self.inner.channel.try_receive() } /// Closes the channel. /// All pending future send attempts will fail. /// Receive attempts will continue to succeed as long as there are items /// stored inside the channel. Further attempts will return `None`. pub fn close(&self) -> CloseStatus { self.inner.channel.close() } /// Returns a stream that will receive values from this channel. /// /// This stream does not yield `None` when the channel is empty, /// instead it yields `None` when it is terminated. pub fn into_stream(self) -> SharedStream { SharedStream { receiver: self, future: None, is_terminated: false, } } } /// A stream that receives from channel using a `GenericReceiver`. /// /// Not driving the `SharedStream` to completion after it has been polled /// might lead to lost wakeup notifications. #[derive(Debug)] pub struct SharedStream where MutexType: 'static + RawMutex, T: 'static, A: 'static + RingBuf, { receiver: GenericReceiver, future: Option>, is_terminated: bool, } impl SharedStream where MutexType: RawMutex, A: 'static + RingBuf, { /// Closes the channel. /// All pending and future send attempts will fail. /// Receive attempts will continue to succeed as long as there are items /// stored inside the channel. Further attempts will fail. pub fn close(&self) -> CloseStatus { self.receiver.close() } } impl Stream for SharedStream where MutexType: RawMutex, A: 'static + RingBuf, { type Item = T; fn poll_next( mut self: Pin<&mut Self>, cx: &mut Context, ) -> Poll> { if self.is_terminated { return Poll::Ready(None); } // Safety: This is safe since this is a pinned projection // that lives as long as the scope. let mut pin_fut = unsafe { self.as_mut().map_unchecked_mut(|v| { // Poll the next element. if v.future.is_none() { v.future.replace(v.receiver.receive()); } &mut v.future }) }; let poll = pin_fut.as_mut().as_pin_mut().unwrap().poll(cx); // Future was resolved, drop it. if poll.is_ready() { pin_fut.set(None); if let Poll::Ready(None) = &poll { // Safety: This is safe because `is_terminated` is never // considered pinned (i.e. not structuraly pinned). unsafe { self.get_unchecked_mut().is_terminated = true }; } } poll } } impl FusedStream for SharedStream where MutexType: RawMutex, A: 'static + RingBuf, { fn is_terminated(&self) -> bool { self.is_terminated } } // Export parking_lot based shared channels in std mode #[cfg(feature = "std")] mod if_std { use super::*; use crate::buffer::GrowingHeapBuf; /// A [`GenericSender`] implementation backed by [`parking_lot`]. /// /// Uses a `GrowingHeapBuf` whose capacity grows dynamically up to /// the given limit. Refer to [`GrowingHeapBuf`] for more information. /// /// [`GrowingHeapBuf`]: ../../buffer/struct.GrowingHeapBuf.html pub type Sender = GenericSender>; /// A [`GenericReceiver`] implementation backed by [`parking_lot`]. /// /// Uses a `GrowingHeapBuf` whose capacity grows dynamically up to /// the given limit. Refer to [`GrowingHeapBuf`] for more information. /// /// [`GrowingHeapBuf`]: ../../buffer/struct.GrowingHeapBuf.html pub type Receiver = GenericReceiver>; /// Creates a new channel with the given buffering capacity /// /// Uses a `GrowingHeapBuf` whose capacity grows dynamically up to /// the given limit. Refer to [`generic_channel`] and [`GrowingHeapBuf`] for more information. /// /// [`GrowingHeapBuf`]: ../../buffer/struct.GrowingHeapBuf.html /// /// ``` /// # use futures_intrusive::channel::shared::channel; /// let (sender, receiver) = channel::(4); /// ``` pub fn channel(capacity: usize) -> (Sender, Receiver) where T: Send, { generic_channel::>( capacity, ) } /// A [`GenericSender`] implementation backed by [`parking_lot`]. pub type UnbufferedSender = GenericSender>; /// A [`GenericReceiver`] implementation backed by [`parking_lot`]. pub type UnbufferedReceiver = GenericReceiver>; /// Creates a new unbuffered channel. /// /// Refer to [`generic_channel`] for details. pub fn unbuffered_channel() -> (Sender, Receiver) where T: Send, { generic_channel::>( 0, ) } } #[cfg(feature = "std")] pub use self::if_std::*; } } #[cfg(feature = "alloc")] pub use self::if_alloc::*;