Skip to content

Commit 9ef0b55

Browse files
committed
zephyr: sync: channel: Add try and timeout variants of recv
Add `try_recv` and `recv_timeout` variants to the channel Receiver. Notably, this allows the special case of a `try_recv` on a bounded channel being safe to call from IRQ context. Notably, unbounded channels are _never_ safe to use from IRQ context. Signed-off-by: David Brown <[email protected]>
1 parent d4108c0 commit 9ef0b55

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

zephyr/src/sync/channel.rs

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,25 +234,34 @@ unsafe impl<T: Send> Send for Receiver<T> {}
234234
unsafe impl<T: Send> Sync for Receiver<T> {}
235235

236236
impl<T> Receiver<T> {
237-
/// Blocks the current thread until a message is received or the channel is empty and
238-
/// disconnected.
237+
/// Waits for a message to be received from the channel, but only for a limited time.
239238
///
240239
/// If the channel is empty and not disconnected, this call will block until the receive
241-
/// operation can proceed. If the channel is empty and becomes disconnected, this call will
240+
/// operation can proceed or the operation times out.
242241
/// wake up and return an error.
243-
pub fn recv(&self) -> Result<T, RecvError> {
242+
pub fn recv_timeout<D>(&self, timeout: D) -> Result<T, RecvError>
243+
where D: Into<Timeout>,
244+
{
244245
match &self.flavor {
245246
ReceiverFlavor::Unbounded { queue, .. } => {
246247
let msg = unsafe {
247-
queue.recv(Forever)
248+
let msg = queue.recv(timeout);
249+
if msg.is_null() {
250+
return Err(RecvError);
251+
}
252+
msg
248253
};
249254
let msg = msg as *mut Message<T>;
250255
let msg = unsafe { Box::from_raw(msg) };
251256
Ok(msg.data)
252257
}
253258
ReceiverFlavor::Bounded(chan) => {
254259
let rawbuf = unsafe {
255-
chan.chan.recv(Forever)
260+
let buf = chan.chan.recv(timeout);
261+
if buf.is_null() {
262+
return Err(RecvError);
263+
}
264+
buf
256265
};
257266
let buf = rawbuf as *mut Message<T>;
258267
let msg: Message<T> = unsafe { buf.read() };
@@ -263,6 +272,26 @@ impl<T> Receiver<T> {
263272
}
264273
}
265274
}
275+
276+
/// Blocks the current thread until a message is received or the channel is empty and
277+
/// disconnected.
278+
///
279+
/// If the channel is empty and not disconnected, this call will block until the receive
280+
/// operation can proceed.
281+
pub fn recv(&self) -> Result<T, RecvError> {
282+
self.recv_timeout(Forever)
283+
}
284+
285+
/// Attempts to receive a message from the channel without blocking.
286+
///
287+
/// This method will either receive a message from the channel immediately, or return an error
288+
/// if the channel is empty.
289+
///
290+
/// This method is safe to use from IRQ context, if and only if the channel was created as a
291+
/// bounded channel.
292+
pub fn try_recv(&self) -> Result<T, RecvError> {
293+
self.recv_timeout(NoWait)
294+
}
266295
}
267296

268297
impl<T> Drop for Receiver<T> {

0 commit comments

Comments
 (0)