@@ -79,6 +79,14 @@ macro_rules! impl_ {
79
79
N : Add <U1 > + Unsigned ,
80
80
Sum <N , U1 >: ArrayLength <T >,
81
81
{
82
+ /// Returns if there are any items to dequeue. When this returns true, at least the
83
+ /// first subsequent dequeue will succeed.
84
+ pub fn ready( & self ) -> bool {
85
+ let tail = unsafe { self . rb. as_ref( ) . tail. load_acquire( ) } ;
86
+ let head = unsafe { self . rb. as_ref( ) . head. load_relaxed( ) } ;
87
+ return head != tail;
88
+ }
89
+
82
90
/// Returns the item in the front of the queue, or `None` if the queue is empty
83
91
pub fn dequeue( & mut self ) -> Option <T > {
84
92
let tail = unsafe { self . rb. as_ref( ) . tail. load_acquire( ) } ;
@@ -119,6 +127,21 @@ macro_rules! impl_ {
119
127
N : Add <U1 > + Unsigned ,
120
128
Sum <N , U1 >: ArrayLength <T >,
121
129
{
130
+ /// Returns if there is any space to enqueue a new item. When this returns true, at
131
+ /// least the first subsequent enqueue will succeed.
132
+ pub fn ready( & self ) -> bool {
133
+ let n = unsafe { self . rb. as_ref( ) . capacity( ) + 1 } ;
134
+ let tail = unsafe { self . rb. as_ref( ) . tail. load_relaxed( ) } ;
135
+ // NOTE we could replace this `load_acquire` with a `load_relaxed` and this method
136
+ // would be sound on most architectures but that change would result in UB according
137
+ // to the C++ memory model, which is what Rust currently uses, so we err on the side
138
+ // of caution and stick to `load_acquire`. Check issue google#sanitizers#882 for
139
+ // more details.
140
+ let head = unsafe { self . rb. as_ref( ) . head. load_acquire( ) } ;
141
+ let next_tail = ( tail + 1 ) % n;
142
+ return next_tail != head;
143
+ }
144
+
122
145
/// Adds an `item` to the end of the queue
123
146
///
124
147
/// Returns back the `item` if the queue is full
0 commit comments