11
11
use std:: cell:: UnsafeCell ;
12
12
use std:: mem:: MaybeUninit ;
13
13
use std:: ptr;
14
- use std:: sync:: atomic:: { self , AtomicUsize , Ordering } ;
14
+ use std:: sync:: atomic:: { self , Ordering } ;
15
15
use std:: time:: Instant ;
16
16
17
17
use crossbeam_utils:: { Backoff , CachePadded } ;
18
18
19
19
use crate :: context:: Context ;
20
20
use crate :: err:: { RecvTimeoutError , SendTimeoutError , TryRecvError , TrySendError } ;
21
21
use crate :: select:: { Operation , SelectHandle , Selected , Token } ;
22
+ use crate :: utils:: AtomicU64 ;
22
23
use crate :: waker:: SyncWaker ;
23
24
24
25
/// A slot in a channel.
25
26
struct Slot < T > {
26
27
/// The current stamp.
27
- stamp : AtomicUsize ,
28
+ stamp : AtomicU64 ,
28
29
29
30
/// The message in this slot.
30
31
msg : UnsafeCell < MaybeUninit < T > > ,
@@ -37,7 +38,7 @@ pub(crate) struct ArrayToken {
37
38
slot : * const u8 ,
38
39
39
40
/// Stamp to store into the slot after reading or writing.
40
- stamp : usize ,
41
+ stamp : u64 ,
41
42
}
42
43
43
44
impl Default for ArrayToken {
@@ -55,20 +56,20 @@ pub(crate) struct Channel<T> {
55
56
/// The head of the channel.
56
57
///
57
58
/// This value is a "stamp" consisting of an index into the buffer, a mark bit, and a lap, but
58
- /// packed into a single `usize `. The lower bits represent the index, while the upper bits
59
+ /// packed into a single `u64 `. The lower bits represent the index, while the upper bits
59
60
/// represent the lap. The mark bit in the head is always zero.
60
61
///
61
62
/// Messages are popped from the head of the channel.
62
- head : CachePadded < AtomicUsize > ,
63
+ head : CachePadded < AtomicU64 > ,
63
64
64
65
/// The tail of the channel.
65
66
///
66
67
/// This value is a "stamp" consisting of an index into the buffer, a mark bit, and a lap, but
67
- /// packed into a single `usize `. The lower bits represent the index, while the upper bits
68
+ /// packed into a single `u64 `. The lower bits represent the index, while the upper bits
68
69
/// represent the lap. The mark bit indicates that the channel is disconnected.
69
70
///
70
71
/// Messages are pushed into the tail of the channel.
71
- tail : CachePadded < AtomicUsize > ,
72
+ tail : CachePadded < AtomicU64 > ,
72
73
73
74
/// The buffer holding slots.
74
75
buffer : Box < [ Slot < T > ] > ,
@@ -77,10 +78,10 @@ pub(crate) struct Channel<T> {
77
78
cap : usize ,
78
79
79
80
/// A stamp with the value of `{ lap: 1, mark: 0, index: 0 }`.
80
- one_lap : usize ,
81
+ one_lap : u64 ,
81
82
82
83
/// If this bit is set in the tail, that means the channel is disconnected.
83
- mark_bit : usize ,
84
+ mark_bit : u64 ,
84
85
85
86
/// Senders waiting while the channel is full.
86
87
senders : SyncWaker ,
@@ -95,7 +96,7 @@ impl<T> Channel<T> {
95
96
assert ! ( cap > 0 , "capacity must be positive" ) ;
96
97
97
98
// Compute constants `mark_bit` and `one_lap`.
98
- let mark_bit = ( cap + 1 ) . next_power_of_two ( ) ;
99
+ let mark_bit = ( cap as u64 + 1 ) . next_power_of_two ( ) ;
99
100
let one_lap = mark_bit * 2 ;
100
101
101
102
// Head is initialized to `{ lap: 0, mark: 0, index: 0 }`.
@@ -105,11 +106,11 @@ impl<T> Channel<T> {
105
106
106
107
// Allocate a buffer of `cap` slots initialized
107
108
// with stamps.
108
- let buffer: Box < [ Slot < T > ] > = ( 0 ..cap)
109
+ let buffer: Box < [ Slot < T > ] > = ( 0 ..cap as u64 )
109
110
. map ( |i| {
110
111
// Set the stamp to `{ lap: 0, mark: 0, index: i }`.
111
112
Slot {
112
- stamp : AtomicUsize :: new ( i) ,
113
+ stamp : AtomicU64 :: new ( i) ,
113
114
msg : UnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ,
114
115
}
115
116
} )
@@ -120,8 +121,8 @@ impl<T> Channel<T> {
120
121
cap,
121
122
one_lap,
122
123
mark_bit,
123
- head : CachePadded :: new ( AtomicUsize :: new ( head) ) ,
124
- tail : CachePadded :: new ( AtomicUsize :: new ( tail) ) ,
124
+ head : CachePadded :: new ( AtomicU64 :: new ( head) ) ,
125
+ tail : CachePadded :: new ( AtomicU64 :: new ( tail) ) ,
125
126
senders : SyncWaker :: new ( ) ,
126
127
receivers : SyncWaker :: new ( ) ,
127
128
}
@@ -151,7 +152,7 @@ impl<T> Channel<T> {
151
152
}
152
153
153
154
// Deconstruct the tail.
154
- let index = tail & ( self . mark_bit - 1 ) ;
155
+ let index = ( tail & ( self . mark_bit - 1 ) ) as usize ;
155
156
let lap = tail & !( self . one_lap - 1 ) ;
156
157
157
158
// Inspect the corresponding slot.
@@ -234,7 +235,7 @@ impl<T> Channel<T> {
234
235
235
236
loop {
236
237
// Deconstruct the head.
237
- let index = head & ( self . mark_bit - 1 ) ;
238
+ let index = ( head & ( self . mark_bit - 1 ) ) as usize ;
238
239
let lap = head & !( self . one_lap - 1 ) ;
239
240
240
241
// Inspect the corresponding slot.
@@ -452,8 +453,8 @@ impl<T> Channel<T> {
452
453
453
454
// If the tail didn't change, we've got consistent values to work with.
454
455
if self . tail . load ( Ordering :: SeqCst ) == tail {
455
- let hix = head & ( self . mark_bit - 1 ) ;
456
- let tix = tail & ( self . mark_bit - 1 ) ;
456
+ let hix = ( head & ( self . mark_bit - 1 ) ) as usize ;
457
+ let tix = ( tail & ( self . mark_bit - 1 ) ) as usize ;
457
458
458
459
return if hix < tix {
459
460
tix - hix
@@ -524,8 +525,8 @@ impl<T> Drop for Channel<T> {
524
525
let head = * self . head . get_mut ( ) ;
525
526
let tail = * self . tail . get_mut ( ) ;
526
527
527
- let hix = head & ( self . mark_bit - 1 ) ;
528
- let tix = tail & ( self . mark_bit - 1 ) ;
528
+ let hix = ( head & ( self . mark_bit - 1 ) ) as usize ;
529
+ let tix = ( tail & ( self . mark_bit - 1 ) ) as usize ;
529
530
530
531
let len = if hix < tix {
531
532
tix - hix
0 commit comments