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