Skip to content

Commit cf025ba

Browse files
authored
sync: support mpsc send with &self (#2861)
Updates the mpsc channel to use the intrusive waker based sempahore. This enables using `Sender` with `&self`. Instead of using `Sender::poll_ready` to ensure capacity and updating the `Sender` state, `async fn Sender::reserve()` is added. This function returns a `Permit` value representing the reserved capacity. Fixes: #2637 Refs: #2718 (intrusive waiters)
1 parent 4186b0a commit cf025ba

19 files changed

+459
-2561
lines changed

tokio-test/src/io.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,9 @@ impl Inner {
200200
}
201201

202202
fn poll_action(&mut self, cx: &mut task::Context<'_>) -> Poll<Option<Action>> {
203-
self.rx.poll_recv(cx)
203+
use futures_core::stream::Stream;
204+
205+
Pin::new(&mut self.rx).poll_next(cx)
204206
}
205207

206208
fn read(&mut self, dst: &mut ReadBuf<'_>) -> io::Result<()> {

tokio/src/signal/unix.rs

+1-29
Original file line numberDiff line numberDiff line change
@@ -391,35 +391,7 @@ impl Signal {
391391
poll_fn(|cx| self.poll_recv(cx)).await
392392
}
393393

394-
/// Polls to receive the next signal notification event, outside of an
395-
/// `async` context.
396-
///
397-
/// `None` is returned if no more events can be received by this stream.
398-
///
399-
/// # Examples
400-
///
401-
/// Polling from a manually implemented future
402-
///
403-
/// ```rust,no_run
404-
/// use std::pin::Pin;
405-
/// use std::future::Future;
406-
/// use std::task::{Context, Poll};
407-
/// use tokio::signal::unix::Signal;
408-
///
409-
/// struct MyFuture {
410-
/// signal: Signal,
411-
/// }
412-
///
413-
/// impl Future for MyFuture {
414-
/// type Output = Option<()>;
415-
///
416-
/// fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
417-
/// println!("polling MyFuture");
418-
/// self.signal.poll_recv(cx)
419-
/// }
420-
/// }
421-
/// ```
422-
pub fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
394+
pub(crate) fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<()>> {
423395
self.rx.poll_recv(cx)
424396
}
425397
}

tokio/src/stream/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ pub trait StreamExt: Stream {
270270
/// # #[tokio::main(basic_scheduler)]
271271
/// async fn main() {
272272
/// # time::pause();
273-
/// let (mut tx1, rx1) = mpsc::channel(10);
274-
/// let (mut tx2, rx2) = mpsc::channel(10);
273+
/// let (tx1, rx1) = mpsc::channel(10);
274+
/// let (tx2, rx2) = mpsc::channel(10);
275275
///
276276
/// let mut rx = rx1.merge(rx2);
277277
///

tokio/src/stream/stream_map.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ use std::task::{Context, Poll};
5757
///
5858
/// #[tokio::main]
5959
/// async fn main() {
60-
/// let (mut tx1, rx1) = mpsc::channel(10);
61-
/// let (mut tx2, rx2) = mpsc::channel(10);
60+
/// let (tx1, rx1) = mpsc::channel(10);
61+
/// let (tx2, rx2) = mpsc::channel(10);
6262
///
6363
/// tokio::spawn(async move {
6464
/// tx1.send(1).await.unwrap();

tokio/src/sync/batch_semaphore.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ impl Semaphore {
165165
/// permits and notifies all pending waiters.
166166
// This will be used once the bounded MPSC is updated to use the new
167167
// semaphore implementation.
168-
#[allow(dead_code)]
169168
pub(crate) fn close(&self) {
170169
let mut waiters = self.waiters.lock().unwrap();
171170
// If the semaphore's permits counter has enough permits for an
@@ -185,6 +184,11 @@ impl Semaphore {
185184
}
186185
}
187186

187+
/// Returns true if the semaphore is closed
188+
pub(crate) fn is_closed(&self) -> bool {
189+
self.permits.load(Acquire) & Self::CLOSED == Self::CLOSED
190+
}
191+
188192
pub(crate) fn try_acquire(&self, num_permits: u32) -> Result<(), TryAcquireError> {
189193
assert!(
190194
num_permits as usize <= Self::MAX_PERMITS,
@@ -194,8 +198,8 @@ impl Semaphore {
194198
let num_permits = (num_permits as usize) << Self::PERMIT_SHIFT;
195199
let mut curr = self.permits.load(Acquire);
196200
loop {
197-
// Has the semaphore closed?git
198-
if curr & Self::CLOSED > 0 {
201+
// Has the semaphore closed?
202+
if curr & Self::CLOSED == Self::CLOSED {
199203
return Err(TryAcquireError::Closed);
200204
}
201205

tokio/src/sync/mod.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
//!
107107
//! #[tokio::main]
108108
//! async fn main() {
109-
//! let (mut tx, mut rx) = mpsc::channel(100);
109+
//! let (tx, mut rx) = mpsc::channel(100);
110110
//!
111111
//! tokio::spawn(async move {
112112
//! for i in 0..10 {
@@ -150,7 +150,7 @@
150150
//! for _ in 0..10 {
151151
//! // Each task needs its own `tx` handle. This is done by cloning the
152152
//! // original handle.
153-
//! let mut tx = tx.clone();
153+
//! let tx = tx.clone();
154154
//!
155155
//! tokio::spawn(async move {
156156
//! tx.send(&b"data to write"[..]).await.unwrap();
@@ -213,7 +213,7 @@
213213
//!
214214
//! // Spawn tasks that will send the increment command.
215215
//! for _ in 0..10 {
216-
//! let mut cmd_tx = cmd_tx.clone();
216+
//! let cmd_tx = cmd_tx.clone();
217217
//!
218218
//! join_handles.push(tokio::spawn(async move {
219219
//! let (resp_tx, resp_rx) = oneshot::channel();
@@ -443,7 +443,6 @@ cfg_sync! {
443443
pub mod oneshot;
444444

445445
pub(crate) mod batch_semaphore;
446-
pub(crate) mod semaphore_ll;
447446
mod semaphore;
448447
pub use semaphore::{Semaphore, SemaphorePermit, OwnedSemaphorePermit};
449448

@@ -473,7 +472,7 @@ cfg_not_sync! {
473472

474473
cfg_signal_internal! {
475474
pub(crate) mod mpsc;
476-
pub(crate) mod semaphore_ll;
475+
pub(crate) mod batch_semaphore;
477476
}
478477
}
479478

0 commit comments

Comments
 (0)