@@ -445,8 +445,12 @@ const MAX_RECEIVERS: usize = usize::MAX >> 2;
445
445
/// than `usize::MAX / 2`.
446
446
#[ track_caller]
447
447
pub fn channel < T : Clone > ( capacity : usize ) -> ( Sender < T > , Receiver < T > ) {
448
- let tx = Sender :: new ( capacity) ;
449
- let rx = tx. subscribe ( ) ;
448
+ // SAFETY: In the line below we are creating one extra receiver, so there will be 1 in total.
449
+ let tx = unsafe { Sender :: new_with_receiver_count ( 1 , capacity) } ;
450
+ let rx = Receiver {
451
+ shared : tx. shared . clone ( ) ,
452
+ next : 0 ,
453
+ } ;
450
454
( tx, rx)
451
455
}
452
456
@@ -464,9 +468,29 @@ impl<T> Sender<T> {
464
468
/// [`broadcast`]: crate::sync::broadcast
465
469
/// [`broadcast::channel`]: crate::sync::broadcast
466
470
#[ track_caller]
467
- pub fn new ( mut capacity : usize ) -> Self {
468
- assert ! ( capacity > 0 , "capacity is empty" ) ;
469
- assert ! ( capacity <= usize :: MAX >> 1 , "requested capacity too large" ) ;
471
+ pub fn new ( capacity : usize ) -> Self {
472
+ // SAFETY: We don't create extra receivers, so there are 0.
473
+ unsafe { Self :: new_with_receiver_count ( 0 , capacity) }
474
+ }
475
+
476
+ /// Creates the sending-half of the [`broadcast`](self) channel, and provide the receiver
477
+ /// count.
478
+ ///
479
+ /// See the documentation of [`broadcast::channel`](self::channel) for more errors when
480
+ /// calling this function.
481
+ ///
482
+ /// # Safety:
483
+ ///
484
+ /// The caller must ensure that the amount of receivers for this Sender is correct before
485
+ /// the channel functionalities are used, the count is zero by default, as this function
486
+ /// does not create any receivers by itself.
487
+ #[ track_caller]
488
+ unsafe fn new_with_receiver_count ( receiver_count : usize , mut capacity : usize ) -> Self {
489
+ assert ! ( capacity > 0 , "broadcast channel capacity cannot be zero" ) ;
490
+ assert ! (
491
+ capacity <= usize :: MAX >> 1 ,
492
+ "broadcast channel capacity exceeded `usize::MAX / 2`"
493
+ ) ;
470
494
471
495
// Round to a power of two
472
496
capacity = capacity. next_power_of_two ( ) ;
@@ -486,7 +510,7 @@ impl<T> Sender<T> {
486
510
mask : capacity - 1 ,
487
511
tail : Mutex :: new ( Tail {
488
512
pos : 0 ,
489
- rx_cnt : 0 ,
513
+ rx_cnt : receiver_count ,
490
514
closed : false ,
491
515
waiters : LinkedList :: new ( ) ,
492
516
} ) ,
@@ -1383,37 +1407,33 @@ mod tests {
1383
1407
1384
1408
#[ test]
1385
1409
fn receiver_count_on_sender_constructor ( ) {
1386
- let count_of = |sender : & Sender < i32 > | sender. shared . tail . lock ( ) . rx_cnt ;
1387
-
1388
1410
let sender = Sender :: < i32 > :: new ( 16 ) ;
1389
- assert_eq ! ( count_of ( & sender) , 0 ) ;
1411
+ assert_eq ! ( sender. receiver_count ( ) , 0 ) ;
1390
1412
1391
1413
let rx_1 = sender. subscribe ( ) ;
1392
- assert_eq ! ( count_of ( & sender) , 1 ) ;
1414
+ assert_eq ! ( sender. receiver_count ( ) , 1 ) ;
1393
1415
1394
1416
let rx_2 = rx_1. resubscribe ( ) ;
1395
- assert_eq ! ( count_of ( & sender) , 2 ) ;
1417
+ assert_eq ! ( sender. receiver_count ( ) , 2 ) ;
1396
1418
1397
1419
let rx_3 = sender. subscribe ( ) ;
1398
- assert_eq ! ( count_of ( & sender) , 3 ) ;
1420
+ assert_eq ! ( sender. receiver_count ( ) , 3 ) ;
1399
1421
1400
1422
drop ( rx_3) ;
1401
1423
drop ( rx_1) ;
1402
- assert_eq ! ( count_of ( & sender) , 1 ) ;
1424
+ assert_eq ! ( sender. receiver_count ( ) , 1 ) ;
1403
1425
1404
1426
drop ( rx_2) ;
1405
- assert_eq ! ( count_of ( & sender) , 0 ) ;
1427
+ assert_eq ! ( sender. receiver_count ( ) , 0 ) ;
1406
1428
}
1407
1429
1408
1430
#[ cfg( not( loom) ) ]
1409
1431
#[ test]
1410
1432
fn receiver_count_on_channel_constructor ( ) {
1411
- let count_of = |sender : & Sender < i32 > | sender. shared . tail . lock ( ) . rx_cnt ;
1412
-
1413
1433
let ( sender, rx) = channel :: < i32 > ( 16 ) ;
1414
- assert_eq ! ( count_of ( & sender) , 1 ) ;
1434
+ assert_eq ! ( sender. receiver_count ( ) , 1 ) ;
1415
1435
1416
1436
let _rx_2 = rx. resubscribe ( ) ;
1417
- assert_eq ! ( count_of ( & sender) , 2 ) ;
1437
+ assert_eq ! ( sender. receiver_count ( ) , 2 ) ;
1418
1438
}
1419
1439
}
0 commit comments