1
1
use std:: cell:: UnsafeCell ;
2
2
use std:: marker:: PhantomData ;
3
- use std:: mem:: { self , MaybeUninit } ;
3
+ use std:: mem:: MaybeUninit ;
4
4
use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
5
5
use std:: thread;
6
6
@@ -38,10 +38,7 @@ pub struct Bounded<T> {
38
38
tail : CachePadded < AtomicUsize > ,
39
39
40
40
/// The buffer holding slots.
41
- buffer : * mut Slot < T > ,
42
-
43
- /// The queue capacity.
44
- cap : usize ,
41
+ buffer : Box < [ Slot < T > ] > ,
45
42
46
43
/// A stamp with the value of `{ lap: 1, mark: 0, index: 0 }`.
47
44
one_lap : usize ,
@@ -64,29 +61,21 @@ impl<T> Bounded<T> {
64
61
let tail = 0 ;
65
62
66
63
// Allocate a buffer of `cap` slots initialized with stamps.
67
- let buffer = {
68
- let mut v: Vec < Slot < T > > = ( 0 ..cap)
69
- . map ( |i| {
70
- // Set the stamp to `{ lap: 0, mark: 0, index: i }`.
71
- Slot {
72
- stamp : AtomicUsize :: new ( i) ,
73
- value : UnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ,
74
- }
75
- } )
76
- . collect ( ) ;
77
-
78
- let ptr = v. as_mut_ptr ( ) ;
79
- mem:: forget ( v) ;
80
- ptr
81
- } ;
64
+ let mut buffer = Vec :: with_capacity ( cap) ;
65
+ for i in 0 ..cap {
66
+ // Set the stamp to `{ lap: 0, mark: 0, index: i }`.
67
+ buffer. push ( Slot {
68
+ stamp : AtomicUsize :: new ( i) ,
69
+ value : UnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ,
70
+ } ) ;
71
+ }
82
72
83
73
// Compute constants `mark_bit` and `one_lap`.
84
74
let mark_bit = ( cap + 1 ) . next_power_of_two ( ) ;
85
75
let one_lap = mark_bit * 2 ;
86
76
87
77
Bounded {
88
- buffer,
89
- cap,
78
+ buffer : buffer. into ( ) ,
90
79
one_lap,
91
80
mark_bit,
92
81
head : CachePadded :: new ( AtomicUsize :: new ( head) ) ,
@@ -110,12 +99,12 @@ impl<T> Bounded<T> {
110
99
let lap = tail & !( self . one_lap - 1 ) ;
111
100
112
101
// Inspect the corresponding slot.
113
- let slot = unsafe { & * self . buffer . add ( index) } ;
102
+ let slot = & self . buffer [ index] ;
114
103
let stamp = slot. stamp . load ( Ordering :: Acquire ) ;
115
104
116
105
// If the tail and the stamp match, we may attempt to push.
117
106
if tail == stamp {
118
- let new_tail = if index + 1 < self . cap {
107
+ let new_tail = if index + 1 < self . buffer . len ( ) {
119
108
// Same lap, incremented index.
120
109
// Set to `{ lap: lap, mark: 0, index: index + 1 }`.
121
110
tail + 1
@@ -173,12 +162,12 @@ impl<T> Bounded<T> {
173
162
let lap = head & !( self . one_lap - 1 ) ;
174
163
175
164
// Inspect the corresponding slot.
176
- let slot = unsafe { & * self . buffer . add ( index) } ;
165
+ let slot = & self . buffer [ index] ;
177
166
let stamp = slot. stamp . load ( Ordering :: Acquire ) ;
178
167
179
168
// If the the stamp is ahead of the head by 1, we may attempt to pop.
180
169
if head + 1 == stamp {
181
- let new = if index + 1 < self . cap {
170
+ let new = if index + 1 < self . buffer . len ( ) {
182
171
// Same lap, incremented index.
183
172
// Set to `{ lap: lap, mark: 0, index: index + 1 }`.
184
173
head + 1
@@ -244,11 +233,11 @@ impl<T> Bounded<T> {
244
233
return if hix < tix {
245
234
tix - hix
246
235
} else if hix > tix {
247
- self . cap - hix + tix
236
+ self . buffer . len ( ) - hix + tix
248
237
} else if ( tail & !self . mark_bit ) == head {
249
238
0
250
239
} else {
251
- self . cap
240
+ self . buffer . len ( )
252
241
} ;
253
242
}
254
243
}
@@ -280,7 +269,7 @@ impl<T> Bounded<T> {
280
269
281
270
/// Returns the capacity of the queue.
282
271
pub fn capacity ( & self ) -> usize {
283
- self . cap
272
+ self . buffer . len ( )
284
273
}
285
274
286
275
/// Closes the queue.
@@ -305,23 +294,18 @@ impl<T> Drop for Bounded<T> {
305
294
// Loop over all slots that hold a value and drop them.
306
295
for i in 0 ..self . len ( ) {
307
296
// Compute the index of the next slot holding a value.
308
- let index = if hix + i < self . cap {
297
+ let index = if hix + i < self . buffer . len ( ) {
309
298
hix + i
310
299
} else {
311
- hix + i - self . cap
300
+ hix + i - self . buffer . len ( )
312
301
} ;
313
302
314
303
// Drop the value in the slot.
304
+ let slot = & self . buffer [ index] ;
315
305
unsafe {
316
- let slot = & * self . buffer . add ( index) ;
317
306
let value = slot. value . get ( ) . read ( ) . assume_init ( ) ;
318
307
drop ( value) ;
319
308
}
320
309
}
321
-
322
- // Finally, deallocate the buffer, but don't run any destructors.
323
- unsafe {
324
- Vec :: from_raw_parts ( self . buffer , 0 , self . cap ) ;
325
- }
326
310
}
327
311
}
0 commit comments