1
//! A oneshot broadcast channel.
2
//!
3
//! The motivation for this channel type was to allow multiple
4
//! receivers to either wait for something to finish,
5
//! or to have an inexpensive method of checking if it has finished.
6
//!
7
//! See [`channel()`].
8

            
9
use std::future::{Future, IntoFuture};
10
use std::ops::Drop;
11
use std::pin::Pin;
12
use std::sync::{Arc, Mutex, OnceLock, Weak};
13
use std::task::{Context, Poll, Waker, ready};
14

            
15
use slotmap_careful::DenseSlotMap;
16

            
17
slotmap_careful::new_key_type! { struct WakerKey; }
18

            
19
/// A [oneshot broadcast][crate::oneshot_broadcast] sender.
20
#[derive(Debug)]
21
pub struct Sender<T> {
22
    /// State shared with all [`Receiver`]s.
23
    shared: Weak<Shared<T>>,
24
}
25

            
26
/// A [oneshot broadcast][crate::oneshot_broadcast] receiver.
27
///
28
/// The `Receiver` offers two methods for receiving the message:
29
///
30
/// 1. [`Receiver::into_future`]
31
///     ```rust
32
///     # use tor_async_utils::oneshot_broadcast::{channel, SenderDropped};
33
///     # async fn x() -> Result<(), SenderDropped> {
34
///     let (tx, rx) = channel();
35
///     tx.send(0);
36
///     let message: u32 = rx.await.unwrap();
37
///     # Ok(())
38
///     # }
39
///     ```
40
///
41
/// 2. [`Receiver::borrowed`]
42
///     ```rust
43
///     # use tor_async_utils::oneshot_broadcast::{channel, SenderDropped};
44
///     # async fn x() -> Result<(), SenderDropped> {
45
///     let (tx, rx) = channel();
46
///     tx.send(0);
47
///     let message: &u32 = rx.borrowed().await.unwrap();
48
///     # Ok(())
49
///     # }
50
///     ```
51
#[derive(Clone, Debug)]
52
pub struct Receiver<T> {
53
    /// State shared with the sender and all other receivers.
54
    shared: Arc<Shared<T>>,
55
}
56

            
57
/// State shared between the sender and receivers.
58
/// Correctness:
59
///
60
/// Sending a message:
61
///  - set the message OnceLock (A)
62
///  - acquire the wakers Mutex
63
///  - take all wakers (B)
64
///  - release the wakers Mutex (C)
65
///  - wake all wakers
66
///
67
/// Polling:
68
///  - if message was set, return it (fast path)
69
///  - acquire the wakers Mutex (D)
70
///  - if message was set, return it (E)
71
///  - add waker (F)
72
///  - release the wakers Mutex
73
///
74
/// When the wakers Mutex is released at (C), a release-store operation is performed by the Mutex,
75
/// which means that the message set at (A) will be seen by all future acquire-load operations by
76
/// that same Mutex. More specifically, after (C) has occurred and when the same mutex is acquired at
77
/// (D), the message set at (A) is guaranteed to be visible at (E). This means that after the wakers
78
/// are taken at (B), no future wakers will be added at (F) and no waker will be "lost".
79
#[derive(Debug)]
80
struct Shared<T> {
81
    /// The message sent from the [`Sender`] to the [`Receiver`]s.
82
    msg: OnceLock<Result<T, SenderDropped>>,
83
    /// The wakers waiting for a value to be sent.
84
    /// Will be set to `Err` after the wakers have been woken.
85
    // the `Result` isn't technically needed here,
86
    // but we use it to help detect bugs;
87
    // see `WakersAlreadyWoken` for details
88
    wakers: Mutex<Result<DenseSlotMap<WakerKey, Waker>, WakersAlreadyWoken>>,
89
}
90

            
91
/// The future from [`Receiver::borrowed`].
92
///
93
/// Will be ready, yielding `&'a T`,
94
/// when the sender sends a message or is dropped.
95
#[derive(Debug)]
96
pub struct BorrowedReceiverFuture<'a, T> {
97
    /// State shared with the sender and all other receivers.
98
    shared: &'a Shared<T>,
99
    /// The key for any waker that we've added to [`Shared::wakers`].
100
    waker_key: Option<WakerKey>,
101
}
102

            
103
/// The future from [`Receiver::into_future`].
104
///
105
/// Will be ready, yielding a clone of `T`,
106
/// when the sender sends a message or is dropped.
107
// Both `ReceiverFuture` and `BorrowedReceiverFuture` have similar fields
108
// but there's no nice way to deduplicated them.
109
// It would have been nice if we could store a `BorrowedReceiverFuture`
110
// holding a reference to our `Arc<Shared>`,
111
// but that would be a self-referential struct,
112
// so we need to duplicate the fields here instead.
113
#[derive(Debug)]
114
pub struct ReceiverFuture<T> {
115
    /// State shared with the sender and all other receivers.
116
    shared: Arc<Shared<T>>,
117
    /// The key for any waker that we've added to [`Shared::wakers`].
118
    waker_key: Option<WakerKey>,
119
}
120

            
121
/// The wakers have already been woken.
122
///
123
/// This is used to help detect if we're trying to access the wakers after they've already been
124
/// woken, which likely indicates a bug. For example, it is a bug if a receiver attempts to add a
125
/// waker after the sender has already sent its message and woken the wakers, since the new waker
126
/// would never be woken.
127
#[derive(Copy, Clone, Debug)]
128
struct WakersAlreadyWoken;
129

            
130
/// The message has already been set, and we can't set it again.
131
#[derive(Copy, Clone, Debug, thiserror::Error)]
132
#[error("the message was already set")]
133
struct MessageAlreadySet;
134

            
135
/// The sender was dropped, so the channel is closed.
136
#[derive(Copy, Clone, Debug, PartialEq, Eq, thiserror::Error)]
137
#[error("the sender was dropped")]
138
#[allow(clippy::exhaustive_structs)]
139
pub struct SenderDropped;
140

            
141
/// All the receivers were dropped, so the channel is closed.
142
#[derive(Copy, Clone, Debug, PartialEq, Eq, thiserror::Error)]
143
#[error("all the receivers were dropped")]
144
#[allow(clippy::exhaustive_structs)]
145
pub struct AllReceiversDropped;
146

            
147
/// Create a new oneshot broadcast channel.
148
///
149
/// ```rust
150
/// # use tor_async_utils::oneshot_broadcast::{channel, SenderDropped};
151
/// # async fn x() -> Result<(), SenderDropped> {
152
/// let (tx, rx) = channel();
153
/// let rx_clone = rx.clone();
154
/// tx.send(0_u8);
155
/// assert_eq!(rx.await, Ok(0));
156
/// assert_eq!(rx_clone.await, Ok(0));
157
/// # Ok(())
158
/// # }
159
/// ```
160
712
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
161
712
    let shared = Arc::new(Shared {
162
712
        msg: OnceLock::new(),
163
712
        wakers: Mutex::new(Ok(DenseSlotMap::with_key())),
164
712
    });
165

            
166
712
    let sender = Sender {
167
712
        shared: Arc::downgrade(&shared),
168
712
    };
169

            
170
712
    let receiver = Receiver { shared };
171

            
172
712
    (sender, receiver)
173
712
}
174

            
175
impl<T> Sender<T> {
176
    /// Send the message to the [`Receiver`]s.
177
    ///
178
    /// The message may be lost if all receivers have been dropped.
179
494
    pub fn send(self, msg: T) {
180
        // set the message and inform the wakers
181
494
        Self::send_and_wake(&self.shared, Ok(msg))
182
            // this 'send()` method takes an owned self,
183
            // and we don't send a message outside of here and the drop handler,
184
            // so this shouldn't be possible
185
494
            .expect("could not set the message");
186
494
    }
187

            
188
    /// Send the message, and wake and clear all wakers.
189
    ///
190
    /// If all receivers have been dropped, then always returns `Ok`.
191
    ///
192
    /// If the message was unable to be set, returns `Err(MessageAlreadySet)`.
193
1154
    fn send_and_wake(
194
1154
        shared: &Weak<Shared<T>>,
195
1154
        msg: Result<T, SenderDropped>,
196
1154
    ) -> Result<(), MessageAlreadySet> {
197
        // Even if the `Weak` upgrade is successful,
198
        // it's possible that the last receiver
199
        // will be dropped during this `send_and_wake` method,
200
        // in which case we will be holding the last `Arc`.
201
1154
        let Some(shared) = shared.upgrade() else {
202
            // all receivers have dropped; nothing to do
203
536
            return Ok(());
204
        };
205

            
206
        // set the message
207
618
        shared.msg.set(msg).or(Err(MessageAlreadySet))?;
208

            
209
386
        let mut wakers = {
210
386
            let mut wakers = shared.wakers.lock().expect("poisoned");
211
            // Take the wakers and drop the mutex guard, releasing the lock.
212
            //
213
            // We could just drain the wakers map in-place here, but instead we replace the map with
214
            // an explicit `WakersAlreadyWoken` state to help catch bugs if something tries adding a
215
            // new waker later after we've already woken the wakers.
216
            //
217
            // The above `msg.set()` will only ever succeed once,
218
            // which means that we should only end up here once.
219
386
            std::mem::replace(&mut *wakers, Err(WakersAlreadyWoken))
220
386
                .expect("wakers were taken more than once")
221
        };
222

            
223
        // Once we drop the mutex guard, which does a release-store on its own atomic, any other
224
        // code which later acquires the wakers mutex is guaranteed to see the msg as "set".
225
        // See comments on `Shared`.
226

            
227
        // Wake while not holding the lock.
228
        // Since the lock is used in `ReceiverFuture::poll` and `ReceiverFuture::drop` and
229
        // should not block for long periods of time,
230
        // we'd prefer not to run third-party waker code here while holding the mutex,
231
        // even if `wake` should typically be fast.
232
570
        for (_key, waker) in wakers.drain() {
233
272
            waker.wake();
234
272
        }
235

            
236
386
        Ok(())
237
1154
    }
238

            
239
    /// Returns `true` if all [`Receiver`]s (and all futures created from the receivers) have been
240
    /// dropped.
241
    ///
242
    /// This can be useful to skip doing extra work to generate the message if the message will be
243
    /// discarded anyways.
244
    // This is for external use.
245
    // It is not always valid to call this internally.
246
    // For example when we've done a `Weak::upgrade` internally, like in `send_and_wake`,
247
    // this won't return the correct value.
248
10
    pub fn is_cancelled(&self) -> bool {
249
10
        self.shared.strong_count() == 0
250
10
    }
251

            
252
    /// Subscribe to this channel, creating a new receiver.
253
    ///
254
    /// Returns an error if all the existing [`Receiver`]s (and all futures created
255
    /// from the receivers) have already been dropped.
256
4
    pub fn subscribe(&self) -> Result<Receiver<T>, AllReceiversDropped> {
257
        Ok(Receiver {
258
4
            shared: self.shared.upgrade().ok_or(AllReceiversDropped)?,
259
        })
260
4
    }
261
}
262

            
263
impl<T> Drop for Sender<T> {
264
660
    fn drop(&mut self) {
265
        // set an error message to indicate that the sender was dropped and inform the wakers;
266
        // it's fine if setting the message fails since it might have been set previously during a
267
        // `send()`
268
660
        let _ = Self::send_and_wake(&self.shared, Err(SenderDropped));
269
660
    }
270
}
271

            
272
impl<T> Receiver<T> {
273
    /// Receive a borrowed message from the [`Sender`].
274
    ///
275
    /// This may be more efficient than [`Receiver::into_future`]
276
    /// and doesn't require `T: Clone`.
277
    ///
278
    /// This is cancellation-safe.
279
472
    pub fn borrowed(&self) -> BorrowedReceiverFuture<'_, T> {
280
472
        BorrowedReceiverFuture {
281
472
            shared: &self.shared,
282
472
            waker_key: None,
283
472
        }
284
472
    }
285

            
286
    /// The receiver is ready.
287
    ///
288
    /// If `true`, the [`Sender`] has either sent its message or been dropped.
289
4895
    pub fn is_ready(&self) -> bool {
290
4895
        self.shared.msg.get().is_some()
291
4895
    }
292
}
293

            
294
impl<T: Clone> IntoFuture for Receiver<T> {
295
    type Output = Result<T, SenderDropped>;
296
    type IntoFuture = ReceiverFuture<T>;
297

            
298
    /// This future is cancellation-safe.
299
96
    fn into_future(self) -> Self::IntoFuture {
300
96
        ReceiverFuture {
301
96
            shared: self.shared,
302
96
            waker_key: None,
303
96
        }
304
96
    }
305
}
306

            
307
impl<'a, T> Future for BorrowedReceiverFuture<'a, T> {
308
    type Output = Result<&'a T, SenderDropped>;
309

            
310
708
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
311
708
        let self_ = self.get_mut();
312
708
        receiver_fut_poll(self_.shared, &mut self_.waker_key, cx.waker())
313
708
    }
314
}
315

            
316
impl<T> Drop for BorrowedReceiverFuture<'_, T> {
317
472
    fn drop(&mut self) {
318
472
        receiver_fut_drop(self.shared, &mut self.waker_key);
319
472
    }
320
}
321

            
322
impl<T: Clone> Future for ReceiverFuture<T> {
323
    type Output = Result<T, SenderDropped>;
324

            
325
128
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
326
128
        let self_ = self.get_mut();
327
128
        let poll = receiver_fut_poll(&self_.shared, &mut self_.waker_key, cx.waker());
328
128
        Poll::Ready(ready!(poll)).map_ok(Clone::clone)
329
128
    }
330
}
331

            
332
impl<T> Drop for ReceiverFuture<T> {
333
96
    fn drop(&mut self) {
334
96
        receiver_fut_drop(&self.shared, &mut self.waker_key);
335
96
    }
336
}
337

            
338
/// The shared poll implementation for receiver futures.
339
836
fn receiver_fut_poll<'a, T>(
340
836
    shared: &'a Shared<T>,
341
836
    waker_key: &mut Option<WakerKey>,
342
836
    new_waker: &Waker,
343
836
) -> Poll<Result<&'a T, SenderDropped>> {
344
    // if the message was already set, return it
345
836
    if let Some(msg) = shared.msg.get() {
346
552
        return Poll::Ready(msg.as_ref().or(Err(SenderDropped)));
347
284
    }
348

            
349
284
    let mut wakers = shared.wakers.lock().expect("poisoned");
350

            
351
    // check again now that we've acquired the mutex
352
284
    if let Some(msg) = shared.msg.get() {
353
        return Poll::Ready(msg.as_ref().or(Err(SenderDropped)));
354
284
    }
355

            
356
    // we have acquired the wakers mutex and checked that the message wasn't set,
357
    // so we know that wakers have not yet been woken
358
    // and it's okay to add our waker to the wakers map
359
284
    let wakers = wakers.as_mut().expect("wakers were already woken");
360

            
361
284
    match waker_key {
362
        // we have added a waker previously
363
8
        Some(waker_key) => {
364
8
            // replace the old entry
365
8
            let waker = wakers
366
8
                .get_mut(*waker_key)
367
8
                // the waker is only removed from the map by our drop handler,
368
8
                // so the waker should never be missing
369
8
                .expect("waker key is missing from map");
370
8
            waker.clone_from(new_waker);
371
8
        }
372
        // we have never added a waker
373
276
        None => {
374
276
            // add a new entry
375
276
            let new_key = wakers.insert(new_waker.clone());
376
276
            *waker_key = Some(new_key);
377
276
        }
378
    }
379

            
380
284
    Poll::Pending
381
836
}
382

            
383
/// The shared drop implementation for receiver futures.
384
568
fn receiver_fut_drop<T>(shared: &Shared<T>, waker_key: &mut Option<WakerKey>) {
385
568
    if let Some(waker_key) = waker_key.take() {
386
276
        let mut wakers = shared.wakers.lock().expect("poisoned");
387
276
        if let Ok(wakers) = wakers.as_mut() {
388
4
            let waker = wakers.remove(waker_key);
389
            // this is the only place that removes the waker from the map,
390
            // so the waker should never be missing
391
4
            debug_assert!(waker.is_some(), "the waker key was not found");
392
272
        }
393
292
    }
394
568
}
395

            
396
#[cfg(test)]
397
mod test {
398
    #![allow(clippy::unwrap_used)]
399

            
400
    use super::*;
401

            
402
    use futures::future::FutureExt;
403
    use tor_rtcompat::SpawnExt;
404

            
405
    impl<T> Shared<T> {
406
        /// Count the number of wakers.
407
        fn count_wakers(&self) -> usize {
408
            self.wakers
409
                .lock()
410
                .expect("poisoned")
411
                .as_ref()
412
                .map(|x| x.len())
413
                .unwrap_or(0)
414
        }
415
    }
416

            
417
    #[test]
418
    fn standard_usage() {
419
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
420
            let (tx, rx) = channel();
421
            tx.send(0_u8);
422
            assert_eq!(rx.borrowed().await, Ok(&0));
423

            
424
            let (tx, rx) = channel();
425
            tx.send(0_u8);
426
            assert_eq!(rx.await, Ok(0));
427
        });
428
    }
429

            
430
    #[test]
431
    fn immediate_drop() {
432
        let _ = channel::<()>();
433

            
434
        let (tx, rx) = channel::<()>();
435
        drop(tx);
436
        drop(rx);
437

            
438
        let (tx, rx) = channel::<()>();
439
        drop(rx);
440
        drop(tx);
441
    }
442

            
443
    #[test]
444
    fn drop_sender() {
445
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
446
            let (tx, rx_1) = channel::<u8>();
447

            
448
            let rx_2 = rx_1.clone();
449
            drop(tx);
450
            let rx_3 = rx_1.clone();
451
            assert_eq!(rx_1.borrowed().await, Err(SenderDropped));
452
            assert_eq!(rx_2.borrowed().await, Err(SenderDropped));
453
            assert_eq!(rx_3.borrowed().await, Err(SenderDropped));
454
        });
455
    }
456

            
457
    #[test]
458
    fn clone_before_send() {
459
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
460
            let (tx, rx_1) = channel();
461

            
462
            let rx_2 = rx_1.clone();
463
            tx.send(0_u8);
464
            assert_eq!(rx_1.borrowed().await, Ok(&0));
465
            assert_eq!(rx_2.borrowed().await, Ok(&0));
466
        });
467
    }
468

            
469
    #[test]
470
    fn clone_after_send() {
471
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
472
            let (tx, rx_1) = channel();
473

            
474
            tx.send(0_u8);
475
            let rx_2 = rx_1.clone();
476
            assert_eq!(rx_1.borrowed().await, Ok(&0));
477
            assert_eq!(rx_2.borrowed().await, Ok(&0));
478
        });
479
    }
480

            
481
    #[test]
482
    fn clone_after_borrowed() {
483
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
484
            let (tx, rx_1) = channel();
485

            
486
            tx.send(0_u8);
487
            assert_eq!(rx_1.borrowed().await, Ok(&0));
488
            let rx_2 = rx_1.clone();
489
            assert_eq!(rx_2.borrowed().await, Ok(&0));
490
        });
491
    }
492

            
493
    #[test]
494
    fn drop_one_receiver() {
495
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
496
            let (tx, rx_1) = channel();
497

            
498
            let rx_2 = rx_1.clone();
499
            drop(rx_1);
500
            tx.send(0_u8);
501
            assert_eq!(rx_2.borrowed().await, Ok(&0));
502
        });
503
    }
504

            
505
    #[test]
506
    fn drop_all_receivers() {
507
        let (tx, rx_1) = channel();
508

            
509
        let rx_2 = rx_1.clone();
510
        drop(rx_1);
511
        drop(rx_2);
512
        tx.send(0_u8);
513
    }
514

            
515
    #[test]
516
    fn drop_fut() {
517
        let (_tx, rx) = channel::<u8>();
518
        let fut = rx.borrowed();
519
        assert_eq!(rx.shared.count_wakers(), 0);
520
        drop(fut);
521
        assert_eq!(rx.shared.count_wakers(), 0);
522

            
523
        // drop after sending
524
        let (tx, rx) = channel();
525
        tx.send(0_u8);
526
        let fut = rx.borrowed();
527
        assert_eq!(rx.shared.count_wakers(), 0);
528
        drop(fut);
529
        assert_eq!(rx.shared.count_wakers(), 0);
530

            
531
        // drop after polling once
532
        let (_tx, rx) = channel::<u8>();
533
        let mut fut = Box::pin(rx.borrowed());
534
        assert_eq!(rx.shared.count_wakers(), 0);
535
        assert_eq!(fut.as_mut().now_or_never(), None);
536
        assert_eq!(rx.shared.count_wakers(), 1);
537
        drop(fut);
538
        assert_eq!(rx.shared.count_wakers(), 0);
539

            
540
        // drop after polling once and send
541
        let (tx, rx) = channel();
542
        let mut fut = Box::pin(rx.borrowed());
543
        assert_eq!(rx.shared.count_wakers(), 0);
544
        assert_eq!(fut.as_mut().now_or_never(), None);
545
        assert_eq!(rx.shared.count_wakers(), 1);
546
        tx.send(0_u8);
547
        assert_eq!(rx.shared.count_wakers(), 0);
548
        drop(fut);
549
    }
550

            
551
    #[test]
552
    fn drop_owned_fut() {
553
        let (_tx, rx) = channel::<u8>();
554
        let fut = rx.clone().into_future();
555
        assert_eq!(rx.shared.count_wakers(), 0);
556
        drop(fut);
557
        assert_eq!(rx.shared.count_wakers(), 0);
558

            
559
        // drop after sending
560
        let (tx, rx) = channel();
561
        tx.send(0_u8);
562
        let fut = rx.clone().into_future();
563
        assert_eq!(rx.shared.count_wakers(), 0);
564
        drop(fut);
565
        assert_eq!(rx.shared.count_wakers(), 0);
566

            
567
        // drop after polling once
568
        let (_tx, rx) = channel::<u8>();
569
        let mut fut = Box::pin(rx.clone().into_future());
570
        assert_eq!(rx.shared.count_wakers(), 0);
571
        assert_eq!(fut.as_mut().now_or_never(), None);
572
        assert_eq!(rx.shared.count_wakers(), 1);
573
        drop(fut);
574
        assert_eq!(rx.shared.count_wakers(), 0);
575

            
576
        // drop after polling once and send
577
        let (tx, rx) = channel();
578
        let mut fut = Box::pin(rx.clone().into_future());
579
        assert_eq!(rx.shared.count_wakers(), 0);
580
        assert_eq!(fut.as_mut().now_or_never(), None);
581
        assert_eq!(rx.shared.count_wakers(), 1);
582
        tx.send(0_u8);
583
        assert_eq!(rx.shared.count_wakers(), 0);
584
        drop(fut);
585
    }
586

            
587
    #[test]
588
    fn is_ready_after_send() {
589
        let (tx, rx_1) = channel();
590
        assert!(!rx_1.is_ready());
591
        let rx_2 = rx_1.clone();
592
        assert!(!rx_2.is_ready());
593

            
594
        tx.send(0_u8);
595

            
596
        assert!(rx_1.is_ready());
597
        assert!(rx_2.is_ready());
598

            
599
        let rx_3 = rx_1.clone();
600
        assert!(rx_3.is_ready());
601
    }
602

            
603
    #[test]
604
    fn is_ready_after_drop() {
605
        let (tx, rx_1) = channel::<u8>();
606
        assert!(!rx_1.is_ready());
607
        let rx_2 = rx_1.clone();
608
        assert!(!rx_2.is_ready());
609

            
610
        drop(tx);
611

            
612
        assert!(rx_1.is_ready());
613
        assert!(rx_2.is_ready());
614

            
615
        let rx_3 = rx_1.clone();
616
        assert!(rx_3.is_ready());
617
    }
618

            
619
    #[test]
620
    fn is_cancelled() {
621
        let (tx, rx) = channel::<u8>();
622
        assert!(!tx.is_cancelled());
623
        drop(rx);
624
        assert!(tx.is_cancelled());
625

            
626
        let (tx, rx_1) = channel::<u8>();
627
        assert!(!tx.is_cancelled());
628
        let rx_2 = rx_1.clone();
629
        drop(rx_1);
630
        assert!(!tx.is_cancelled());
631
        drop(rx_2);
632
        assert!(tx.is_cancelled());
633
    }
634

            
635
    #[test]
636
    fn recv_in_task() {
637
        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
638
            let (tx, rx) = channel();
639

            
640
            let join = rt
641
                .spawn_with_handle(async move {
642
                    assert_eq!(rx.borrowed().await, Ok(&0));
643
                    assert_eq!(rx.await, Ok(0));
644
                })
645
                .unwrap();
646

            
647
            tx.send(0_u8);
648

            
649
            join.await;
650
        });
651
    }
652

            
653
    #[test]
654
    fn recv_multiple_in_task() {
655
        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
656
            let (tx, rx) = channel();
657
            let rx_1 = rx.clone();
658
            let rx_2 = rx.clone();
659

            
660
            let join_1 = rt
661
                .spawn_with_handle(async move {
662
                    assert_eq!(rx_1.borrowed().await, Ok(&0));
663
                })
664
                .unwrap();
665
            let join_2 = rt
666
                .spawn_with_handle(async move {
667
                    assert_eq!(rx_2.await, Ok(0));
668
                })
669
                .unwrap();
670

            
671
            tx.send(0_u8);
672

            
673
            join_1.await;
674
            join_2.await;
675
            assert_eq!(rx.borrowed().await, Ok(&0));
676
        });
677
    }
678

            
679
    #[test]
680
    fn recv_multiple_times() {
681
        tor_rtmock::MockRuntime::test_with_various(|_rt| async move {
682
            let (tx, rx) = channel();
683
            let rx_subscribed = tx.subscribe().unwrap();
684

            
685
            tx.send(0_u8);
686
            assert_eq!(rx.borrowed().await, Ok(&0));
687
            assert_eq!(rx.borrowed().await, Ok(&0));
688
            assert_eq!(rx.clone().await, Ok(0));
689
            assert_eq!(rx.await, Ok(0));
690
            assert_eq!(rx_subscribed.await, Ok(0));
691
        });
692
    }
693

            
694
    #[test]
695
    fn stress() {
696
        // In general we don't have control over the runtime and where/when tasks are scheduled,
697
        // so we try as best as possible to send the message while simultaneously creating new
698
        // receivers and waiting on them.
699
        // It's possible this might be entirely ineffective since we don't enforce any specific
700
        // scheduler behaviour here,
701
        // but in the worst case it's still a test with multiple receivers on different tasks,
702
        // so is useful to have.
703
        //
704
        // The `test_with_various` helper uses `MockExecutor` with two different deterministic
705
        // scheduling policies.
706
        // At least at the time of writing,
707
        // when this test uses `MockExecutor` with its "queue" scheduling policy
708
        // the "send" occurs after 20 of the tasks have begun waiting.
709
        tor_rtmock::MockRuntime::test_with_various(|rt| async move {
710
            let (tx, rx) = channel();
711

            
712
            rt.spawn(async move {
713
                // this tries to delay the send a little bit
714
                // to give time for some of the receiver tasks to start
715
                for _ in 0..20 {
716
                    tor_rtcompat::task::yield_now().await;
717
                }
718
                tx.send(0_u8);
719
            })
720
            .unwrap();
721

            
722
            let mut joins = vec![];
723
            for _ in 0..100 {
724
                let rx_clone = rx.clone();
725
                let join = rt
726
                    .spawn_with_handle(async move { rx_clone.borrowed().await.cloned() })
727
                    .unwrap();
728
                joins.push(join);
729
                // allows the send task to make progress if single-threaded
730
                tor_rtcompat::task::yield_now().await;
731
            }
732

            
733
            for join in joins {
734
                assert!(matches!(join.await, Ok(0)));
735
            }
736
        });
737
    }
738
}