Skip to content

Commit 03b890f

Browse files
bors[bot]jmgao
andauthored
Merge #110
110: Add Queue::peek. r=japaric a=jmgao Co-authored-by: Josh Gao <[email protected]>
2 parents 9e2e5ae + eae66b9 commit 03b890f

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/spsc/mod.rs

+38
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ where
117117
U: sealed::Uxx,
118118
C: sealed::XCore,
119119
{
120+
fn get(&self) -> &U {
121+
unsafe { &*self.v.get() }
122+
}
123+
120124
fn get_mut(&mut self) -> &mut U {
121125
unsafe { &mut *self.v.get() }
122126
}
@@ -341,6 +345,40 @@ macro_rules! impl_ {
341345
N: ArrayLength<T>,
342346
C: sealed::XCore,
343347
{
348+
/// Returns a reference to the item in the front of the queue without dequeuing, or
349+
/// `None` if the queue is empty.
350+
///
351+
/// # Examples
352+
/// ```
353+
/// use heapless::spsc::Queue;
354+
/// use heapless::consts::*;
355+
///
356+
/// let mut queue: Queue<u8, U235, _> = Queue::u8();
357+
/// let (mut producer, mut consumer) = queue.split();
358+
/// assert_eq!(None, consumer.peek());
359+
/// producer.enqueue(1);
360+
/// assert_eq!(Some(&1), consumer.peek());
361+
/// assert_eq!(Some(1), consumer.dequeue());
362+
/// assert_eq!(None, consumer.peek());
363+
/// ```
364+
pub fn peek(&self) -> Option<&T> {
365+
let cap = self.capacity();
366+
367+
let head = self.0.head.get();
368+
let tail = self.0.tail.get();
369+
370+
let p = self.0.buffer.as_ptr();
371+
372+
if *head != *tail {
373+
let item = unsafe {
374+
&*(p as *const T).add(usize::from(*head % cap))
375+
};
376+
Some(item)
377+
} else {
378+
None
379+
}
380+
}
381+
344382
/// Returns the item in the front of the queue, or `None` if the queue is empty
345383
pub fn dequeue(&mut self) -> Option<T> {
346384
let cap = self.capacity();

src/spsc/split.rs

+35
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,32 @@ macro_rules! impl_ {
8484
return head != tail;
8585
}
8686

87+
/// Returns the item in the front of the queue without dequeuing, or `None` if the queue is empty.
88+
///
89+
/// # Examples
90+
/// ```
91+
/// use heapless::spsc::Queue;
92+
/// use heapless::consts::*;
93+
///
94+
/// let mut queue: Queue<u8, U235, _> = Queue::u8();
95+
/// let (mut producer, mut consumer) = queue.split();
96+
/// assert_eq!(None, consumer.peek());
97+
/// producer.enqueue(1);
98+
/// assert_eq!(Some(&1), consumer.peek());
99+
/// assert_eq!(Some(1), consumer.dequeue());
100+
/// assert_eq!(None, consumer.peek());
101+
/// ```
102+
pub fn peek(&self) -> Option<&T> {
103+
let head = unsafe { self.rb.as_ref().0.head.load_relaxed() };
104+
let tail = unsafe { self.rb.as_ref().0.tail.load_acquire() };
105+
106+
if head != tail {
107+
Some(unsafe { self._peek(head) })
108+
} else {
109+
None
110+
}
111+
}
112+
87113
/// Returns the item in the front of the queue, or `None` if the queue is empty
88114
pub fn dequeue(&mut self) -> Option<T> {
89115
let head = unsafe { self.rb.as_ref().0.head.load_relaxed() };
@@ -107,6 +133,15 @@ macro_rules! impl_ {
107133
self._dequeue(head) // ▲
108134
}
109135

136+
unsafe fn _peek(&self, head: $uxx) -> &T {
137+
let rb = self.rb.as_ref();
138+
139+
let cap = rb.capacity();
140+
141+
let item = (rb.0.buffer.as_ptr() as *const T).add(usize::from(head % cap));
142+
&*item
143+
}
144+
110145
unsafe fn _dequeue(&mut self, head: $uxx) -> T {
111146
let rb = self.rb.as_ref();
112147

0 commit comments

Comments
 (0)