@@ -224,18 +224,27 @@ impl<T, const N: usize> Queue<T, N> {
224224 }
225225 }
226226
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+ ///
227240 /// # Unsafety
228241 ///
229242 /// If the queue is full this operation will leak a value (T's destructor won't run on
230243 /// the value that got overwritten by `item`), *and* will allow the `dequeue` operation
231244 /// to create a copy of `item`, which could result in `T`'s destructor running on `item`
232245 /// 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)
239248 }
240249
241250 // The memory for dequeuing is "owned" by the head pointer,.
@@ -256,6 +265,29 @@ impl<T, const N: usize> Queue<T, N> {
256265 }
257266 }
258267
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+
259291 /// Splits a queue into producer and consumer endpoints
260292 pub fn split ( & mut self ) -> ( Producer < ' _ , T , N > , Consumer < ' _ , T , N > ) {
261293 ( Producer { rb : self } , Consumer { rb : self } )
@@ -464,6 +496,15 @@ impl<'a, T, const N: usize> Consumer<'a, T, N> {
464496 unsafe { self . rb . inner_dequeue ( ) }
465497 }
466498
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+
467508 /// Returns if there are any items to dequeue. When this returns `true`, at least the
468509 /// first subsequent dequeue will succeed
469510 #[ inline]
@@ -505,14 +546,20 @@ impl<'a, T, const N: usize> Consumer<'a, T, N> {
505546}
506547
507548impl < ' 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
511550 #[ inline]
512551 pub fn enqueue ( & mut self , val : T ) -> Result < ( ) , T > {
513552 unsafe { self . rb . inner_enqueue ( val) }
514553 }
515554
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+
516563 /// Returns if there is any space to enqueue a new item. When this returns true, at
517564 /// least the first subsequent enqueue will succeed.
518565 #[ inline]
0 commit comments