Skip to content

Commit fa8bdf9

Browse files
committed
take self as receiver types on downgrade and upgrade
1 parent ef6fabb commit fa8bdf9

File tree

3 files changed

+29
-25
lines changed

3 files changed

+29
-25
lines changed

tokio/src/sync/mpsc/bounded.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::loom::sync::Arc;
12
use crate::sync::batch_semaphore::{self as semaphore, TryAcquireError};
23
use crate::sync::mpsc::chan;
34
use crate::sync::mpsc::error::{SendError, TryRecvError, TrySendError};
@@ -54,7 +55,7 @@ pub struct Sender<T> {
5455
///
5556
/// ```
5657
pub struct WeakSender<T> {
57-
chan: chan::Tx<T, Semaphore>,
58+
chan: Arc<chan::Chan<T, Semaphore>>,
5859
}
5960

6061
/// Permits to send one value into the channel.
@@ -1031,7 +1032,7 @@ impl<T> Sender<T> {
10311032
/// towards RAII semantics, i.e. if all `Sender` instances of the
10321033
/// channel were dropped and only `WeakSender` instances remain,
10331034
/// the channel is closed.
1034-
pub fn downgrade(self) -> WeakSender<T> {
1035+
pub fn downgrade(&self) -> WeakSender<T> {
10351036
// Note: If this is the last `Sender` instance we want to close the
10361037
// channel when downgrading, so it's important to move into `self` here.
10371038

@@ -1069,8 +1070,8 @@ impl<T> WeakSender<T> {
10691070
/// Tries to convert a WeakSender into a [`Sender`]. This will return `Some`
10701071
/// if there are other `Sender` instances alive and the channel wasn't
10711072
/// previously dropped, otherwise `None` is returned.
1072-
pub fn upgrade(self) -> Option<Sender<T>> {
1073-
self.chan.upgrade().map(Sender::new)
1073+
pub fn upgrade(&self) -> Option<Sender<T>> {
1074+
chan::Tx::upgrade(self.chan.clone()).map(Sender::new)
10741075
}
10751076
}
10761077

tokio/src/sync/mpsc/chan.rs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) trait Semaphore {
4747
fn is_closed(&self) -> bool;
4848
}
4949

50-
struct Chan<T, S> {
50+
pub(crate) struct Chan<T, S> {
5151
/// Notifies all tasks listening for the receiver being dropped.
5252
notify_rx_closed: Notify,
5353

@@ -130,34 +130,25 @@ impl<T, S> Tx<T, S> {
130130
Tx { inner: chan }
131131
}
132132

133-
pub(super) fn downgrade(self) -> Self {
134-
if self.inner.tx_count.fetch_sub(1, AcqRel) == 1 {
135-
// Close the list, which sends a `Close` message
136-
self.inner.tx.close();
137-
138-
// Notify the receiver
139-
self.wake_rx();
140-
}
141-
142-
self
133+
pub(super) fn downgrade(&self) -> Arc<Chan<T, S>> {
134+
self.inner.clone()
143135
}
144136

145137
// Returns the upgraded channel or None if the upgrade failed.
146-
pub(super) fn upgrade(self) -> Option<Self> {
147-
let mut tx_count = self.inner.tx_count.load(Acquire);
138+
pub(super) fn upgrade(chan: Arc<Chan<T, S>>) -> Option<Self> {
139+
let mut tx_count = chan.tx_count.load(Acquire);
148140

149141
loop {
150142
if tx_count == 0 {
151143
// channel is closed
152144
return None;
153145
}
154146

155-
match self
156-
.inner
147+
match chan
157148
.tx_count
158149
.compare_exchange_weak(tx_count, tx_count + 1, AcqRel, Acquire)
159150
{
160-
Ok(_) => return Some(self),
151+
Ok(_) => return Some(Tx { inner: chan }),
161152
Err(prev_count) => tx_count = prev_count,
162153
}
163154
}

tokio/tests/sync_mpsc.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -667,9 +667,10 @@ fn recv_timeout_panic() {
667667
#[tokio::test]
668668
async fn weak_sender() {
669669
let (tx, mut rx) = channel(11);
670-
let tx_weak = tx.clone().downgrade();
671670

672671
let tx_weak = tokio::spawn(async move {
672+
let tx_weak = tx.clone().downgrade();
673+
673674
for i in 0..10 {
674675
if tx.send(i).await.is_err() {
675676
return None;
@@ -703,10 +704,9 @@ async fn weak_sender() {
703704
}
704705
}
705706

706-
if let Some(tx_weak) = tx_weak {
707-
let upgraded = tx_weak.upgrade();
708-
assert!(upgraded.is_none());
709-
}
707+
let tx_weak = tx_weak.unwrap();
708+
let upgraded = tx_weak.upgrade();
709+
assert!(upgraded.is_none());
710710
}
711711

712712
#[tokio::test]
@@ -887,6 +887,7 @@ async fn downgrade_upgrade_sender_success() {
887887
async fn downgrade_upgrade_sender_failure() {
888888
let (tx, _rx) = mpsc::channel::<i32>(1);
889889
let weak_tx = tx.downgrade();
890+
drop(tx);
890891
assert!(weak_tx.upgrade().is_none());
891892
}
892893

@@ -921,3 +922,14 @@ async fn downgrade_upgrade_get_permit_no_senders() {
921922
let weak_tx = tx2.downgrade();
922923
assert!(weak_tx.upgrade().is_some());
923924
}
925+
926+
// Tests that `Clone` of `WeakSender` doesn't decrement `tx_count`.
927+
#[tokio::test]
928+
async fn test_weak_sender_clone() {
929+
let (tx, _rx) = mpsc::channel::<i32>(1);
930+
let tx_weak = tx.downgrade();
931+
let tx_weak2 = tx.downgrade();
932+
drop(tx);
933+
934+
assert!(tx_weak.upgrade().is_none() && tx_weak2.upgrade().is_none());
935+
}

0 commit comments

Comments
 (0)