@@ -224,18 +224,27 @@ impl<T, const N: usize> Queue<T, N> {
224
224
}
225
225
}
226
226
227
+ // The memory for enqueueing is "owned" by the tail pointer.
228
+ // NOTE: This internal function uses internal mutability to allow the [`Producer`] to enqueue
229
+ // items without doing pointer arithmetic and accessing internal fields of this type.
230
+ unsafe fn inner_enqueue_unchecked ( & self , val : T ) {
231
+ let current_tail = self . tail . load ( Ordering :: Relaxed ) ;
232
+
233
+ ( self . buffer . get_unchecked ( current_tail) . get ( ) ) . write ( MaybeUninit :: new ( val) ) ;
234
+ self . tail
235
+ . store ( Self :: increment ( current_tail) , Ordering :: Release ) ;
236
+ }
237
+
238
+ /// Adds an `item` to the end of the queue, without checking if it's full
239
+ ///
227
240
/// # Unsafety
228
241
///
229
242
/// If the queue is full this operation will leak a value (T's destructor won't run on
230
243
/// the value that got overwritten by `item`), *and* will allow the `dequeue` operation
231
244
/// to create a copy of `item`, which could result in `T`'s destructor running on `item`
232
245
/// twice.
233
- unsafe fn enqueue_unchecked ( & mut self , val : T ) {
234
- let current_tail = self . tail . load ( Ordering :: Relaxed ) ;
235
-
236
- ( self . buffer . get_unchecked ( current_tail) . get ( ) ) . write ( MaybeUninit :: new ( val) ) ;
237
- self . tail
238
- . store ( Self :: increment ( current_tail) , Ordering :: Release ) ;
246
+ pub unsafe fn enqueue_unchecked ( & mut self , val : T ) {
247
+ self . inner_enqueue_unchecked ( val)
239
248
}
240
249
241
250
// The memory for dequeuing is "owned" by the head pointer,.
@@ -256,6 +265,29 @@ impl<T, const N: usize> Queue<T, N> {
256
265
}
257
266
}
258
267
268
+ // The memory for dequeuing is "owned" by the head pointer,.
269
+ // NOTE: This internal function uses internal mutability to allow the [`Consumer`] to dequeue
270
+ // items without doing pointer arithmetic and accessing internal fields of this type.
271
+ unsafe fn inner_dequeue_unchecked ( & self ) -> T {
272
+ let current_head = self . head . load ( Ordering :: Relaxed ) ;
273
+ let v = ( self . buffer . get_unchecked ( current_head) . get ( ) as * const T ) . read ( ) ;
274
+
275
+ self . head
276
+ . store ( Self :: increment ( current_head) , Ordering :: Release ) ;
277
+
278
+ v
279
+ }
280
+
281
+ /// Returns the item in the front of the queue, without checking if there is something in the
282
+ /// queue
283
+ ///
284
+ /// # Unsafety
285
+ ///
286
+ /// If the queue is empty this operation will return uninitialized memory.
287
+ pub unsafe fn dequeue_unchecked ( & mut self ) -> T {
288
+ self . inner_dequeue_unchecked ( )
289
+ }
290
+
259
291
/// Splits a queue into producer and consumer endpoints
260
292
pub fn split ( & mut self ) -> ( Producer < ' _ , T , N > , Consumer < ' _ , T , N > ) {
261
293
( Producer { rb : self } , Consumer { rb : self } )
@@ -464,6 +496,15 @@ impl<'a, T, const N: usize> Consumer<'a, T, N> {
464
496
unsafe { self . rb . inner_dequeue ( ) }
465
497
}
466
498
499
+ /// Returns the item in the front of the queue, without checking if there are elements in the
500
+ /// queue
501
+ ///
502
+ /// See [`Queue::dequeue_unchecked`] for safety
503
+ #[ inline]
504
+ pub unsafe fn dequeue_unchecked ( & mut self ) -> T {
505
+ self . rb . inner_dequeue_unchecked ( )
506
+ }
507
+
467
508
/// Returns if there are any items to dequeue. When this returns `true`, at least the
468
509
/// first subsequent dequeue will succeed
469
510
#[ inline]
@@ -505,14 +546,20 @@ impl<'a, T, const N: usize> Consumer<'a, T, N> {
505
546
}
506
547
507
548
impl < ' a , T , const N : usize > Producer < ' a , T , N > {
508
- /// Adds an `item` to the end of the queue
509
- ///
510
- /// Returns back the `item` if the queue is full
549
+ /// Adds an `item` to the end of the queue, returns back the `item` if the queue is full
511
550
#[ inline]
512
551
pub fn enqueue ( & mut self , val : T ) -> Result < ( ) , T > {
513
552
unsafe { self . rb . inner_enqueue ( val) }
514
553
}
515
554
555
+ /// Adds an `item` to the end of the queue, without checking if the queue is full
556
+ ///
557
+ /// See [`Queue::enqueue_unchecked`] for safety
558
+ #[ inline]
559
+ pub unsafe fn enqueue_unchecked ( & mut self , val : T ) {
560
+ self . rb . inner_enqueue_unchecked ( val)
561
+ }
562
+
516
563
/// Returns if there is any space to enqueue a new item. When this returns true, at
517
564
/// least the first subsequent enqueue will succeed.
518
565
#[ inline]
0 commit comments