Skip to main content

osal_rs/traits/
queue.rs

1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
18 *
19 ***************************************************************************/
20
21//! Queue traits for inter-task communication.
22//!
23//! Provides both raw byte-based queues and type-safe streamed queues
24//! for message passing between tasks.
25//!
26//! # Overview
27//!
28//! Queues implement FIFO (First-In-First-Out) message passing between tasks,
29//! enabling the producer-consumer pattern and other inter-task communication
30//! patterns. Messages are copied into and out of the queue.
31//!
32//! # Queue Types
33//!
34//! - **`Queue`**: Raw byte-oriented queue for variable-sized or untyped data
35//! - **`QueueStreamed<T>`**: Type-safe queue for structured messages
36//!
37//! # Communication Patterns
38//!
39//! - **Producer-Consumer**: One or more producers send messages, one consumer processes them
40//! - **Work Queue**: Distribute tasks among multiple worker tasks
41//! - **Event Notification**: Send status updates or notifications between tasks
42//!
43//! # Timeout Behavior
44//!
45//! - `0`: Non-blocking - return immediately if queue is full/empty
46//! - `n`: Wait up to `n` ticks for space/data to become available
47//! - `TickType::MAX`: Block indefinitely until operation succeeds
48//!
49//! # Examples
50//!
51//! ```
52//! use osal_rs::os::{Queue, QueueFn};
53//!
54//! // Create a queue for 10 messages of 4 bytes each
55//! let queue = Queue::new(10, 4).unwrap();
56//!
57//! // Producer task
58//! let data = [1u8, 2, 3, 4];
59//! queue.post(&data, 1000).unwrap();
60//!
61//! // Consumer task
62//! let mut buffer = [0u8; 4];
63//! queue.fetch(&mut buffer, 1000).unwrap();
64//! ```
65#[cfg(not(feature = "serde"))]
66use crate::os::Deserialize;
67
68#[cfg(feature = "serde")]
69use osal_rs_serde::Deserialize;
70
71use crate::os::types::TickType;
72use crate::utils::Result;
73
74/// Raw byte-oriented queue for inter-task message passing.
75///
76/// This trait defines a FIFO queue that works with raw byte arrays,
77/// suitable for variable-sized messages or when type safety is not required.
78///
79/// # Memory Layout
80///
81/// The queue capacity is fixed at creation time. Each message slot can
82/// hold up to the maximum message size specified during creation.
83///
84/// # Thread Safety
85///
86/// All methods are thread-safe. Multiple producers and consumers can
87/// safely access the same queue concurrently.
88///
89/// # Performance
90///
91/// Messages are copied into and out of the queue. For large messages,
92/// consider using a queue of pointers or references instead.
93///
94/// # Examples
95///
96/// ```ignore
97/// use osal_rs::os::Queue;
98/// 
99/// // Create queue: 10 slots, 32 bytes per message
100/// let queue = Queue::new(10, 32).unwrap();
101/// 
102/// // Producer sends data
103/// let data = [1, 2, 3, 4];
104/// queue.post(&data, 100).unwrap();
105/// 
106/// // Consumer receives data
107/// let mut buffer = [0u8; 32];
108/// queue.fetch(&mut buffer, 100).unwrap();
109/// assert_eq!(&buffer[..4], &[1, 2, 3, 4]);
110/// ```
111pub trait Queue {
112
113    /// Returns `true` if the underlying OS handle is null, i.e. the mutex
114    /// has not been created yet or has already been deleted.
115    fn is_null(&self) -> bool;
116
117    /// Fetches a message from the queue (blocking).
118    ///
119    /// Removes and retrieves the oldest message from the queue (FIFO order).
120    /// Blocks the calling task if the queue is empty.
121    ///
122    /// # Parameters
123    ///
124    /// * `buffer` - Buffer to receive the message data (should match queue message size)
125    /// * `time` - Maximum ticks to wait for a message:
126    ///   - `0`: Return immediately if empty
127    ///   - `n`: Wait up to `n` ticks
128    ///   - `TickType::MAX`: Wait forever
129    ///
130    /// # Returns
131    ///
132    /// * `Ok(())` - Message received successfully
133    /// * `Err(Error::Timeout)` - Queue was empty for entire timeout period
134    /// * `Err(Error)` - Other error occurred
135    ///
136    /// # Examples
137    ///
138    /// ```ignore
139    /// let mut buffer = [0u8; 16];
140    /// 
141    /// // Wait up to 1000 ticks
142    /// match queue.fetch(&mut buffer, 1000) {
143    ///     Ok(()) => println!("Received: {:?}", buffer),
144    ///     Err(_) => println!("Timeout - no message available"),
145    /// }
146    /// ```
147    fn fetch(&self, buffer: &mut [u8], time: TickType) -> Result<()>;
148
149    /// Fetches a message from ISR context (non-blocking).
150    ///
151    /// ISR-safe version of `fetch()`. Returns immediately without blocking.
152    /// Must only be called from interrupt context.
153    ///
154    /// # Parameters
155    ///
156    /// * `buffer` - Buffer to receive the message data
157    ///
158    /// # Returns
159    ///
160    /// * `Ok(())` - Message received successfully
161    /// * `Err(Error)` - Queue is empty
162    ///
163    /// # Examples
164    ///
165    /// ```ignore
166    /// // In interrupt handler
167    /// let mut buffer = [0u8; 16];
168    /// if queue.fetch_from_isr(&mut buffer).is_ok() {
169    ///     // Process message quickly
170    /// }
171    /// ```
172    fn fetch_from_isr(&self, buffer: &mut [u8]) -> Result<()>;
173    
174    /// Posts a message to the queue (blocking).
175    ///
176    /// Adds a new message to the end of the queue (FIFO order).
177    /// Blocks the calling task if the queue is full.
178    ///
179    /// # Parameters
180    ///
181    /// * `item` - The message data to send (must not exceed queue message size)
182    /// * `time` - Maximum ticks to wait if queue is full:
183    ///   - `0`: Return immediately if full
184    ///   - `n`: Wait up to `n` ticks for space
185    ///   - `TickType::MAX`: Wait forever
186    ///
187    /// # Returns
188    ///
189    /// * `Ok(())` - Message sent successfully
190    /// * `Err(Error::Timeout)` - Queue was full for entire timeout period
191    /// * `Err(Error)` - Other error occurred
192    ///
193    /// # Examples
194    ///
195    /// ```ignore
196    /// let data = [1, 2, 3, 4];
197    /// 
198    /// // Try to send, wait up to 1000 ticks if full
199    /// match queue.post(&data, 1000) {
200    ///     Ok(()) => println!("Sent successfully"),
201    ///     Err(_) => println!("Queue full, couldn't send"),
202    /// }
203    /// ```
204    fn post(&self, item: &[u8], time: TickType) -> Result<()>;
205    
206    /// Posts a message from ISR context (non-blocking).
207    ///
208    /// ISR-safe version of `post()`. Returns immediately without blocking.
209    /// Must only be called from interrupt context.
210    ///
211    /// # Parameters
212    ///
213    /// * `item` - The message data to send
214    ///
215    /// # Returns
216    ///
217    /// * `Ok(())` - Message sent successfully
218    /// * `Err(Error)` - Queue is full
219    ///
220    /// # Examples
221    ///
222    /// ```ignore
223    /// // In interrupt handler
224    /// let data = [0x42, 0x13];
225    /// if queue.post_from_isr(&data).is_err() {
226    ///     // Queue full, message dropped
227    /// }
228    /// ```
229    fn post_from_isr(&self, item: &[u8]) -> Result<()>;
230
231    /// Deletes the queue and frees its resources.
232    ///
233    /// # Safety
234    ///
235    /// Ensure no tasks are blocked on this queue before deletion.
236    /// Calling this while tasks are waiting may cause undefined behavior.
237    ///
238    /// # Examples
239    ///
240    /// ```ignore
241    /// let mut queue = Queue::new(10, 16).unwrap();
242    /// // Use queue...
243    /// queue.delete();
244    /// ```
245    fn delete(&mut self);
246}
247
248/// Type-safe queue for structured message passing.
249///
250/// This trait provides a queue that works with specific types,
251/// offering compile-time type safety for queue operations.
252///
253/// # Type Safety
254///
255/// Unlike raw `Queue`, `QueueStreamed` ensures that only messages
256/// of type `T` can be sent and received, preventing type confusion
257/// at compile time.
258///
259/// # Serialization
260///
261/// Messages are automatically serialized when sent and deserialized
262/// when received. The type `T` must implement the `Deserialize` trait.
263///
264/// # Type Parameters
265///
266/// * `T` - The message type (must implement `Deserialize`)
267///
268/// # Examples
269///
270/// ```ignore
271/// use osal_rs::os::QueueStreamed;
272/// use osal_rs::traits::Deserialize;
273/// 
274/// #[derive(Clone, Copy)]
275/// struct SensorData {
276///     id: u32,
277///     temperature: i16,
278///     humidity: u8,
279/// }
280/// 
281/// impl Deserialize for SensorData {
282///     fn from_bytes(bytes: &[u8]) -> Result<Self> {
283///         // Deserialization logic
284///     }
285/// }
286/// 
287/// let queue = QueueStreamed::<SensorData>::new(10, size_of::<SensorData>()).unwrap();
288/// 
289/// // Producer
290/// let data = SensorData { id: 1, temperature: 235, humidity: 65 };
291/// queue.post(&data, 100).unwrap();
292/// 
293/// // Consumer
294/// let mut received = SensorData { id: 0, temperature: 0, humidity: 0 };
295/// queue.fetch(&mut received, 100).unwrap();
296/// assert_eq!(received.id, 1);
297/// ```
298
299pub trait QueueStreamed<T> 
300where 
301    T: Deserialize + Sized {
302
303    /// Fetches a typed message from the queue (blocking).
304    ///
305    /// Removes and deserializes the oldest message from the queue.
306    /// Blocks the calling task if the queue is empty.
307    ///
308    /// # Parameters
309    ///
310    /// * `buffer` - Mutable reference to receive the deserialized message
311    /// * `time` - Maximum ticks to wait for a message:
312    ///   - `0`: Return immediately if empty
313    ///   - `n`: Wait up to `n` ticks
314    ///   - `TickType::MAX`: Wait forever
315    ///
316    /// # Returns
317    ///
318    /// * `Ok(())` - Message received and deserialized successfully
319    /// * `Err(Error::Timeout)` - Queue was empty for entire timeout period
320    /// * `Err(Error)` - Deserialization error or other error
321    ///
322    /// # Examples
323    ///
324    /// ```ignore
325    /// let mut msg = Message::default();
326    /// 
327    /// match queue.fetch(&mut msg, 1000) {
328    ///     Ok(()) => println!("Received message: {:?}", msg),
329    ///     Err(_) => println!("No message available"),
330    /// }
331    /// ```
332    fn fetch(&self, buffer: &mut T, time: TickType) -> Result<()>;
333
334    /// Fetches a typed message from ISR context (non-blocking).
335    ///
336    /// ISR-safe version of `fetch()`. Returns immediately without blocking.
337    /// Must only be called from interrupt context.
338    ///
339    /// # Parameters
340    ///
341    /// * `buffer` - Mutable reference to receive the deserialized message
342    ///
343    /// # Returns
344    ///
345    /// * `Ok(())` - Message received and deserialized successfully
346    /// * `Err(Error)` - Queue is empty or deserialization failed
347    ///
348    /// # Examples
349    ///
350    /// ```ignore
351    /// // In interrupt handler
352    /// let mut msg = Message::default();
353    /// if queue.fetch_from_isr(&mut msg).is_ok() {
354    ///     // Process message
355    /// }
356    /// ```
357    fn fetch_from_isr(&self, buffer: &mut T) -> Result<()>;
358    
359    /// Posts a typed message to the queue (blocking).
360    ///
361    /// Serializes and adds a new message to the end of the queue.
362    /// Blocks the calling task if the queue is full.
363    ///
364    /// # Parameters
365    ///
366    /// * `item` - Reference to the message to serialize and send
367    /// * `time` - Maximum ticks to wait if queue is full:
368    ///   - `0`: Return immediately if full
369    ///   - `n`: Wait up to `n` ticks for space
370    ///   - `TickType::MAX`: Wait forever
371    ///
372    /// # Returns
373    ///
374    /// * `Ok(())` - Message serialized and sent successfully
375    /// * `Err(Error::Timeout)` - Queue was full for entire timeout period
376    /// * `Err(Error)` - Serialization error or other error
377    ///
378    /// # Examples
379    ///
380    /// ```ignore
381    /// let msg = Message { id: 42, value: 100 };
382    /// 
383    /// match queue.post(&msg, 1000) {
384    ///     Ok(()) => println!("Sent successfully"),
385    ///     Err(_) => println!("Failed to send"),
386    /// }
387    /// ```
388    fn post(&self, item: &T, time: TickType) -> Result<()>;
389
390    /// Posts a typed message from ISR context (non-blocking).
391    ///
392    /// ISR-safe version of `post()`. Returns immediately without blocking.
393    /// Must only be called from interrupt context.
394    ///
395    /// # Parameters
396    ///
397    /// * `item` - Reference to the message to serialize and send
398    ///
399    /// # Returns
400    ///
401    /// * `Ok(())` - Message serialized and sent successfully
402    /// * `Err(Error)` - Queue is full or serialization failed
403    ///
404    /// # Examples
405    ///
406    /// ```ignore
407    /// // In interrupt handler
408    /// let msg = Message { id: 1, value: 42 };
409    /// if queue.post_from_isr(&msg).is_err() {
410    ///     // Queue full, message dropped
411    /// }
412    /// ```
413    fn post_from_isr(&self, item: &T) -> Result<()>;
414
415    /// Deletes the queue and frees its resources.
416    ///
417    /// # Safety
418    ///
419    /// Ensure no tasks are blocked on this queue before deletion.
420    /// Calling this while tasks are waiting may cause undefined behavior.
421    ///
422    /// # Examples
423    ///
424    /// ```ignore
425    /// let mut queue = QueueStreamed::<Message>::new(10, size_of::<Message>()).unwrap();
426    /// // Use queue...
427    /// queue.delete();
428    /// ```
429    fn delete(&mut self);
430}