@@ -208,7 +208,14 @@ impl<T, S: Storage> QueueInner<T, S> {
208
208
209
209
/// Returns the item in the front of the queue, or `None` if the queue is empty.
210
210
pub fn dequeue ( & self ) -> Option < T > {
211
- unsafe { dequeue ( S :: as_ptr ( self . buffer . get ( ) ) , & self . dequeue_pos , self . mask ( ) ) }
211
+ unsafe {
212
+ dequeue (
213
+ S :: as_ptr ( self . buffer . get ( ) ) ,
214
+ & self . dequeue_pos ,
215
+ & self . enqueue_pos ,
216
+ self . mask ( ) ,
217
+ )
218
+ }
212
219
}
213
220
214
221
/// Adds an `item` to the end of the queue.
@@ -218,6 +225,7 @@ impl<T, S: Storage> QueueInner<T, S> {
218
225
unsafe {
219
226
enqueue (
220
227
S :: as_ptr ( self . buffer . get ( ) ) ,
228
+ & self . dequeue_pos ,
221
229
& self . enqueue_pos ,
222
230
self . mask ( ) ,
223
231
item,
@@ -255,18 +263,25 @@ impl<T> Cell<T> {
255
263
}
256
264
}
257
265
266
+ const CONTENTION_RETRY_COUNT : usize = 10000 ;
267
+
258
268
unsafe fn dequeue < T > (
259
269
buffer : * mut Cell < T > ,
260
270
dequeue_pos : & AtomicTargetSize ,
271
+ enqueue_pos : & AtomicTargetSize ,
261
272
mask : UintSize ,
262
273
) -> Option < T > {
263
274
let mut pos = dequeue_pos. load ( Ordering :: Relaxed ) ;
264
275
265
276
let mut cell;
277
+ let mut seq;
278
+ let mut dif;
279
+ let mut contention_retry_count = 0 ;
280
+
266
281
loop {
267
282
cell = buffer. add ( usize:: from ( pos & mask) ) ;
268
- let seq = ( * cell) . sequence . load ( Ordering :: Acquire ) ;
269
- let dif = ( seq as IntSize ) . wrapping_sub ( ( pos. wrapping_add ( 1 ) ) as IntSize ) ;
283
+ seq = ( * cell) . sequence . load ( Ordering :: Acquire ) ;
284
+ dif = ( seq as IntSize ) . wrapping_sub ( ( pos. wrapping_add ( 1 ) ) as IntSize ) ;
270
285
271
286
match dif. cmp ( & 0 ) {
272
287
core:: cmp:: Ordering :: Equal => {
@@ -283,6 +298,16 @@ unsafe fn dequeue<T>(
283
298
}
284
299
}
285
300
core:: cmp:: Ordering :: Less => {
301
+ if pos != enqueue_pos. load ( Ordering :: Relaxed )
302
+ && contention_retry_count < CONTENTION_RETRY_COUNT
303
+ {
304
+ // In this case according to the positions the queue is not empty
305
+ // This suggests that there is a enqueue operations that is in progress in some other task
306
+ // Therefore we can wait a bit hoping that the other task can finish its `enqueue` operation complete
307
+ core:: hint:: spin_loop ( ) ;
308
+ contention_retry_count += 1 ;
309
+ continue ;
310
+ }
286
311
return None ;
287
312
}
288
313
core:: cmp:: Ordering :: Greater => {
@@ -300,13 +325,15 @@ unsafe fn dequeue<T>(
300
325
301
326
unsafe fn enqueue < T > (
302
327
buffer : * mut Cell < T > ,
328
+ dequeue_pos : & AtomicTargetSize ,
303
329
enqueue_pos : & AtomicTargetSize ,
304
330
mask : UintSize ,
305
331
item : T ,
306
332
) -> Result < ( ) , T > {
307
333
let mut pos = enqueue_pos. load ( Ordering :: Relaxed ) ;
308
334
309
335
let mut cell;
336
+ let mut contention_retry_count = 0 ;
310
337
loop {
311
338
cell = buffer. add ( usize:: from ( pos & mask) ) ;
312
339
let seq = ( * cell) . sequence . load ( Ordering :: Acquire ) ;
@@ -325,8 +352,19 @@ unsafe fn enqueue<T>(
325
352
{
326
353
break ;
327
354
}
355
+ pos = enqueue_pos. load ( Ordering :: Relaxed ) ;
328
356
}
329
357
core:: cmp:: Ordering :: Less => {
358
+ if dequeue_pos. load ( Ordering :: Relaxed ) . wrapping_add ( mask + 1 ) != pos
359
+ && contention_retry_count < CONTENTION_RETRY_COUNT
360
+ {
361
+ // In this case according to the positions the queue is not full
362
+ // This suggests that there is a dequeue operation that is in progress in some other task
363
+ // Therefore we can wait a bit hoping that the other task can finish its `dequeue` operation completes
364
+ core:: hint:: spin_loop ( ) ;
365
+ contention_retry_count += 1 ;
366
+ continue ;
367
+ }
330
368
return Err ( item) ;
331
369
}
332
370
core:: cmp:: Ordering :: Greater => {
0 commit comments