118
118
119
119
use crate :: loom:: cell:: UnsafeCell ;
120
120
use crate :: loom:: sync:: atomic:: { AtomicBool , AtomicUsize } ;
121
- use crate :: loom:: sync:: { Arc , Mutex , MutexGuard , RwLock , RwLockReadGuard } ;
121
+ use crate :: loom:: sync:: { Arc , Mutex , MutexGuard } ;
122
122
use crate :: util:: linked_list:: { self , GuardedLinkedList , LinkedList } ;
123
123
use crate :: util:: WakeList ;
124
124
@@ -303,7 +303,7 @@ use self::error::{RecvError, SendError, TryRecvError};
303
303
/// Data shared between senders and receivers.
304
304
struct Shared < T > {
305
305
/// slots in the channel.
306
- buffer : Box < [ RwLock < Slot < T > > ] > ,
306
+ buffer : Box < [ Mutex < Slot < T > > ] > ,
307
307
308
308
/// Mask a position -> index.
309
309
mask : usize ,
@@ -347,7 +347,7 @@ struct Slot<T> {
347
347
///
348
348
/// The value is set by `send` when the write lock is held. When a reader
349
349
/// drops, `rem` is decremented. When it hits zero, the value is dropped.
350
- val : UnsafeCell < Option < T > > ,
350
+ val : Option < T > ,
351
351
}
352
352
353
353
/// An entry in the wait queue.
@@ -385,7 +385,7 @@ generate_addr_of_methods! {
385
385
}
386
386
387
387
struct RecvGuard < ' a , T > {
388
- slot : RwLockReadGuard < ' a , Slot < T > > ,
388
+ slot : MutexGuard < ' a , Slot < T > > ,
389
389
}
390
390
391
391
/// Receive a value future.
@@ -394,11 +394,15 @@ struct Recv<'a, T> {
394
394
receiver : & ' a mut Receiver < T > ,
395
395
396
396
/// Entry in the waiter `LinkedList`.
397
- waiter : UnsafeCell < Waiter > ,
397
+ waiter : WaiterCell ,
398
398
}
399
399
400
- unsafe impl < ' a , T : Send > Send for Recv < ' a , T > { }
401
- unsafe impl < ' a , T : Send > Sync for Recv < ' a , T > { }
400
+ // The wrapper around `UnsafeCell` isolates the unsafe impl `Send` and `Sync`
401
+ // from `Recv`.
402
+ struct WaiterCell ( UnsafeCell < Waiter > ) ;
403
+
404
+ unsafe impl Send for WaiterCell { }
405
+ unsafe impl Sync for WaiterCell { }
402
406
403
407
/// Max number of receivers. Reserve space to lock.
404
408
const MAX_RECEIVERS : usize = usize:: MAX >> 2 ;
@@ -466,12 +470,6 @@ pub fn channel<T: Clone>(capacity: usize) -> (Sender<T>, Receiver<T>) {
466
470
( tx, rx)
467
471
}
468
472
469
- unsafe impl < T : Send > Send for Sender < T > { }
470
- unsafe impl < T : Send > Sync for Sender < T > { }
471
-
472
- unsafe impl < T : Send > Send for Receiver < T > { }
473
- unsafe impl < T : Send > Sync for Receiver < T > { }
474
-
475
473
impl < T > Sender < T > {
476
474
/// Creates the sending-half of the [`broadcast`] channel.
477
475
///
@@ -510,10 +508,10 @@ impl<T> Sender<T> {
510
508
let mut buffer = Vec :: with_capacity ( capacity) ;
511
509
512
510
for i in 0 ..capacity {
513
- buffer. push ( RwLock :: new ( Slot {
511
+ buffer. push ( Mutex :: new ( Slot {
514
512
rem : AtomicUsize :: new ( 0 ) ,
515
513
pos : ( i as u64 ) . wrapping_sub ( capacity as u64 ) ,
516
- val : UnsafeCell :: new ( None ) ,
514
+ val : None ,
517
515
} ) ) ;
518
516
}
519
517
@@ -599,7 +597,7 @@ impl<T> Sender<T> {
599
597
tail. pos = tail. pos . wrapping_add ( 1 ) ;
600
598
601
599
// Get the slot
602
- let mut slot = self . shared . buffer [ idx] . write ( ) . unwrap ( ) ;
600
+ let mut slot = self . shared . buffer [ idx] . lock ( ) ;
603
601
604
602
// Track the position
605
603
slot. pos = pos;
@@ -608,7 +606,7 @@ impl<T> Sender<T> {
608
606
slot. rem . with_mut ( |v| * v = rem) ;
609
607
610
608
// Write the value
611
- slot. val = UnsafeCell :: new ( Some ( value) ) ;
609
+ slot. val = Some ( value) ;
612
610
613
611
// Release the slot lock before notifying the receivers.
614
612
drop ( slot) ;
@@ -695,7 +693,7 @@ impl<T> Sender<T> {
695
693
while low < high {
696
694
let mid = low + ( high - low) / 2 ;
697
695
let idx = base_idx. wrapping_add ( mid) & self . shared . mask ;
698
- if self . shared . buffer [ idx] . read ( ) . unwrap ( ) . rem . load ( SeqCst ) == 0 {
696
+ if self . shared . buffer [ idx] . lock ( ) . rem . load ( SeqCst ) == 0 {
699
697
low = mid + 1 ;
700
698
} else {
701
699
high = mid;
@@ -737,7 +735,7 @@ impl<T> Sender<T> {
737
735
let tail = self . shared . tail . lock ( ) ;
738
736
739
737
let idx = ( tail. pos . wrapping_sub ( 1 ) & self . shared . mask as u64 ) as usize ;
740
- self . shared . buffer [ idx] . read ( ) . unwrap ( ) . rem . load ( SeqCst ) == 0
738
+ self . shared . buffer [ idx] . lock ( ) . rem . load ( SeqCst ) == 0
741
739
}
742
740
743
741
/// Returns the number of active receivers.
@@ -1057,7 +1055,7 @@ impl<T> Receiver<T> {
1057
1055
let idx = ( self . next & self . shared . mask as u64 ) as usize ;
1058
1056
1059
1057
// The slot holding the next value to read
1060
- let mut slot = self . shared . buffer [ idx] . read ( ) . unwrap ( ) ;
1058
+ let mut slot = self . shared . buffer [ idx] . lock ( ) ;
1061
1059
1062
1060
if slot. pos != self . next {
1063
1061
// Release the `slot` lock before attempting to acquire the `tail`
@@ -1074,7 +1072,7 @@ impl<T> Receiver<T> {
1074
1072
let mut tail = self . shared . tail . lock ( ) ;
1075
1073
1076
1074
// Acquire slot lock again
1077
- slot = self . shared . buffer [ idx] . read ( ) . unwrap ( ) ;
1075
+ slot = self . shared . buffer [ idx] . lock ( ) ;
1078
1076
1079
1077
// Make sure the position did not change. This could happen in the
1080
1078
// unlikely event that the buffer is wrapped between dropping the
@@ -1367,12 +1365,12 @@ impl<'a, T> Recv<'a, T> {
1367
1365
fn new ( receiver : & ' a mut Receiver < T > ) -> Recv < ' a , T > {
1368
1366
Recv {
1369
1367
receiver,
1370
- waiter : UnsafeCell :: new ( Waiter {
1368
+ waiter : WaiterCell ( UnsafeCell :: new ( Waiter {
1371
1369
queued : AtomicBool :: new ( false ) ,
1372
1370
waker : None ,
1373
1371
pointers : linked_list:: Pointers :: new ( ) ,
1374
1372
_p : PhantomPinned ,
1375
- } ) ,
1373
+ } ) ) ,
1376
1374
}
1377
1375
}
1378
1376
@@ -1384,7 +1382,7 @@ impl<'a, T> Recv<'a, T> {
1384
1382
is_unpin :: < & mut Receiver < T > > ( ) ;
1385
1383
1386
1384
let me = self . get_unchecked_mut ( ) ;
1387
- ( me. receiver , & me. waiter )
1385
+ ( me. receiver , & me. waiter . 0 )
1388
1386
}
1389
1387
}
1390
1388
}
@@ -1418,6 +1416,7 @@ impl<'a, T> Drop for Recv<'a, T> {
1418
1416
// `Shared::notify_rx` before we drop the object.
1419
1417
let queued = self
1420
1418
. waiter
1419
+ . 0
1421
1420
. with ( |ptr| unsafe { ( * ptr) . queued . load ( Acquire ) } ) ;
1422
1421
1423
1422
// If the waiter is queued, we need to unlink it from the waiters list.
@@ -1432,6 +1431,7 @@ impl<'a, T> Drop for Recv<'a, T> {
1432
1431
// `Relaxed` order suffices because we hold the tail lock.
1433
1432
let queued = self
1434
1433
. waiter
1434
+ . 0
1435
1435
. with_mut ( |ptr| unsafe { ( * ptr) . queued . load ( Relaxed ) } ) ;
1436
1436
1437
1437
if queued {
@@ -1440,7 +1440,7 @@ impl<'a, T> Drop for Recv<'a, T> {
1440
1440
// safety: tail lock is held and the wait node is verified to be in
1441
1441
// the list.
1442
1442
unsafe {
1443
- self . waiter . with_mut ( |ptr| {
1443
+ self . waiter . 0 . with_mut ( |ptr| {
1444
1444
tail. waiters . remove ( ( & mut * ptr) . into ( ) ) ;
1445
1445
} ) ;
1446
1446
}
@@ -1486,16 +1486,15 @@ impl<'a, T> RecvGuard<'a, T> {
1486
1486
where
1487
1487
T : Clone ,
1488
1488
{
1489
- self . slot . val . with ( |ptr| unsafe { ( * ptr ) . clone ( ) } )
1489
+ self . slot . val . clone ( )
1490
1490
}
1491
1491
}
1492
1492
1493
1493
impl < ' a , T > Drop for RecvGuard < ' a , T > {
1494
1494
fn drop ( & mut self ) {
1495
1495
// Decrement the remaining counter
1496
1496
if 1 == self . slot . rem . fetch_sub ( 1 , SeqCst ) {
1497
- // Safety: Last receiver, drop the value
1498
- self . slot . val . with_mut ( |ptr| unsafe { * ptr = None } ) ;
1497
+ self . slot . val = None ;
1499
1498
}
1500
1499
}
1501
1500
}
0 commit comments