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
356
pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
161
356
    let shared = Arc::new(Shared {
162
356
        msg: OnceLock::new(),
163
356
        wakers: Mutex::new(Ok(DenseSlotMap::with_key())),
164
356
    });
165

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

            
170
356
    let receiver = Receiver { shared };
171

            
172
356
    (sender, receiver)
173
356
}
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
247
    pub fn send(self, msg: T) {
180
        // set the message and inform the wakers
181
247
        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
247
            .expect("could not set the message");
186
247
    }
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
577
    fn send_and_wake(
194
577
        shared: &Weak<Shared<T>>,
195
577
        msg: Result<T, SenderDropped>,
196
577
    ) -> 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
577
        let Some(shared) = shared.upgrade() else {
202
            // all receivers have dropped; nothing to do
203
286
            return Ok(());
204
        };
205

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

            
209
184
        let mut wakers = {
210
184
            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
184
            std::mem::replace(&mut *wakers, Err(WakersAlreadyWoken))
220
184
                .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
276
        for (_key, waker) in wakers.drain() {
233
136
            waker.wake();
234
136
        }
235

            
236
184
        Ok(())
237
577
    }
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
5
    pub fn is_cancelled(&self) -> bool {
249
5
        self.shared.strong_count() == 0
250
5
    }
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
2
    pub fn subscribe(&self) -> Result<Receiver<T>, AllReceiversDropped> {
257
        Ok(Receiver {
258
2
            shared: self.shared.upgrade().ok_or(AllReceiversDropped)?,
259
        })
260
2
    }
261
}
262

            
263
impl<T> Drop for Sender<T> {
264
330
    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
330
        let _ = Self::send_and_wake(&self.shared, Err(SenderDropped));
269
330
    }
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
236
    pub fn borrowed(&self) -> BorrowedReceiverFuture<'_, T> {
280
236
        BorrowedReceiverFuture {
281
236
            shared: &self.shared,
282
236
            waker_key: None,
283
236
        }
284
236
    }
285

            
286
    /// The receiver is ready.
287
    ///
288
    /// If `true`, the [`Sender`] has either sent its message or been dropped.
289
2470
    pub fn is_ready(&self) -> bool {
290
2470
        self.shared.msg.get().is_some()
291
2470
    }
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
48
    fn into_future(self) -> Self::IntoFuture {
300
48
        ReceiverFuture {
301
48
            shared: self.shared,
302
48
            waker_key: None,
303
48
        }
304
48
    }
305
}
306

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

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

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

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

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

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

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

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

            
351
    // check again now that we've acquired the mutex
352
142
    if let Some(msg) = shared.msg.get() {
353
        return Poll::Ready(msg.as_ref().or(Err(SenderDropped)));
354
142
    }
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
142
    let wakers = wakers.as_mut().expect("wakers were already woken");
360

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

            
380
142
    Poll::Pending
381
418
}
382

            
383
/// The shared drop implementation for receiver futures.
384
284
fn receiver_fut_drop<T>(shared: &Shared<T>, waker_key: &mut Option<WakerKey>) {
385
284
    if let Some(waker_key) = waker_key.take() {
386
138
        let mut wakers = shared.wakers.lock().expect("poisoned");
387
138
        if let Ok(wakers) = wakers.as_mut() {
388
2
            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
2
            debug_assert!(waker.is_some(), "the waker key was not found");
392
136
        }
393
146
    }
394
284
}
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
}