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//! ```ignore
52//! use osal_rs::os::Queue;
53//!
54//! // Create a queue for 10 messages of 16 bytes each
55//! let queue = Queue::new(10, 16).unwrap();
56//!
57//! // Producer task
58//! let data = [1, 2, 3, 4];
59//! queue.post(&data, 1000).unwrap();
60//!
61//! // Consumer task
62//! let mut buffer = [0u8; 16];
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    /// Fetches a message from the queue (blocking).
113    ///
114    /// Removes and retrieves the oldest message from the queue (FIFO order).
115    /// Blocks the calling task if the queue is empty.
116    ///
117    /// # Parameters
118    ///
119    /// * `buffer` - Buffer to receive the message data (should match queue message size)
120    /// * `time` - Maximum ticks to wait for a message:
121    ///   - `0`: Return immediately if empty
122    ///   - `n`: Wait up to `n` ticks
123    ///   - `TickType::MAX`: Wait forever
124    ///
125    /// # Returns
126    ///
127    /// * `Ok(())` - Message received successfully
128    /// * `Err(Error::Timeout)` - Queue was empty for entire timeout period
129    /// * `Err(Error)` - Other error occurred
130    ///
131    /// # Examples
132    ///
133    /// ```ignore
134    /// let mut buffer = [0u8; 16];
135    /// 
136    /// // Wait up to 1000 ticks
137    /// match queue.fetch(&mut buffer, 1000) {
138    ///     Ok(()) => println!("Received: {:?}", buffer),
139    ///     Err(_) => println!("Timeout - no message available"),
140    /// }
141    /// ```
142    fn fetch(&self, buffer: &mut [u8], time: TickType) -> Result<()>;
143
144    /// Fetches a message from ISR context (non-blocking).
145    ///
146    /// ISR-safe version of `fetch()`. Returns immediately without blocking.
147    /// Must only be called from interrupt context.
148    ///
149    /// # Parameters
150    ///
151    /// * `buffer` - Buffer to receive the message data
152    ///
153    /// # Returns
154    ///
155    /// * `Ok(())` - Message received successfully
156    /// * `Err(Error)` - Queue is empty
157    ///
158    /// # Examples
159    ///
160    /// ```ignore
161    /// // In interrupt handler
162    /// let mut buffer = [0u8; 16];
163    /// if queue.fetch_from_isr(&mut buffer).is_ok() {
164    ///     // Process message quickly
165    /// }
166    /// ```
167    fn fetch_from_isr(&self, buffer: &mut [u8]) -> Result<()>;
168    
169    /// Posts a message to the queue (blocking).
170    ///
171    /// Adds a new message to the end of the queue (FIFO order).
172    /// Blocks the calling task if the queue is full.
173    ///
174    /// # Parameters
175    ///
176    /// * `item` - The message data to send (must not exceed queue message size)
177    /// * `time` - Maximum ticks to wait if queue is full:
178    ///   - `0`: Return immediately if full
179    ///   - `n`: Wait up to `n` ticks for space
180    ///   - `TickType::MAX`: Wait forever
181    ///
182    /// # Returns
183    ///
184    /// * `Ok(())` - Message sent successfully
185    /// * `Err(Error::Timeout)` - Queue was full for entire timeout period
186    /// * `Err(Error)` - Other error occurred
187    ///
188    /// # Examples
189    ///
190    /// ```ignore
191    /// let data = [1, 2, 3, 4];
192    /// 
193    /// // Try to send, wait up to 1000 ticks if full
194    /// match queue.post(&data, 1000) {
195    ///     Ok(()) => println!("Sent successfully"),
196    ///     Err(_) => println!("Queue full, couldn't send"),
197    /// }
198    /// ```
199    fn post(&self, item: &[u8], time: TickType) -> Result<()>;
200    
201    /// Posts a message from ISR context (non-blocking).
202    ///
203    /// ISR-safe version of `post()`. Returns immediately without blocking.
204    /// Must only be called from interrupt context.
205    ///
206    /// # Parameters
207    ///
208    /// * `item` - The message data to send
209    ///
210    /// # Returns
211    ///
212    /// * `Ok(())` - Message sent successfully
213    /// * `Err(Error)` - Queue is full
214    ///
215    /// # Examples
216    ///
217    /// ```ignore
218    /// // In interrupt handler
219    /// let data = [0x42, 0x13];
220    /// if queue.post_from_isr(&data).is_err() {
221    ///     // Queue full, message dropped
222    /// }
223    /// ```
224    fn post_from_isr(&self, item: &[u8]) -> Result<()>;
225
226    /// Deletes the queue and frees its resources.
227    ///
228    /// # Safety
229    ///
230    /// Ensure no tasks are blocked on this queue before deletion.
231    /// Calling this while tasks are waiting may cause undefined behavior.
232    ///
233    /// # Examples
234    ///
235    /// ```ignore
236    /// let mut queue = Queue::new(10, 16).unwrap();
237    /// // Use queue...
238    /// queue.delete();
239    /// ```
240    fn delete(&mut self);
241}
242
243/// Type-safe queue for structured message passing.
244///
245/// This trait provides a queue that works with specific types,
246/// offering compile-time type safety for queue operations.
247///
248/// # Type Safety
249///
250/// Unlike raw `Queue`, `QueueStreamed` ensures that only messages
251/// of type `T` can be sent and received, preventing type confusion
252/// at compile time.
253///
254/// # Serialization
255///
256/// Messages are automatically serialized when sent and deserialized
257/// when received. The type `T` must implement the `Deserialize` trait.
258///
259/// # Type Parameters
260///
261/// * `T` - The message type (must implement `Deserialize`)
262///
263/// # Examples
264///
265/// ```ignore
266/// use osal_rs::os::QueueStreamed;
267/// use osal_rs::traits::Deserialize;
268/// 
269/// #[derive(Clone, Copy)]
270/// struct SensorData {
271///     id: u32,
272///     temperature: i16,
273///     humidity: u8,
274/// }
275/// 
276/// impl Deserialize for SensorData {
277///     fn from_bytes(bytes: &[u8]) -> Result<Self> {
278///         // Deserialization logic
279///     }
280/// }
281/// 
282/// let queue = QueueStreamed::<SensorData>::new(10, size_of::<SensorData>()).unwrap();
283/// 
284/// // Producer
285/// let data = SensorData { id: 1, temperature: 235, humidity: 65 };
286/// queue.post(&data, 100).unwrap();
287/// 
288/// // Consumer
289/// let mut received = SensorData { id: 0, temperature: 0, humidity: 0 };
290/// queue.fetch(&mut received, 100).unwrap();
291/// assert_eq!(received.id, 1);
292/// ```
293
294pub trait QueueStreamed<T> 
295where 
296    T: Deserialize + Sized {
297
298    /// Fetches a typed message from the queue (blocking).
299    ///
300    /// Removes and deserializes the oldest message from the queue.
301    /// Blocks the calling task if the queue is empty.
302    ///
303    /// # Parameters
304    ///
305    /// * `buffer` - Mutable reference to receive the deserialized message
306    /// * `time` - Maximum ticks to wait for a message:
307    ///   - `0`: Return immediately if empty
308    ///   - `n`: Wait up to `n` ticks
309    ///   - `TickType::MAX`: Wait forever
310    ///
311    /// # Returns
312    ///
313    /// * `Ok(())` - Message received and deserialized successfully
314    /// * `Err(Error::Timeout)` - Queue was empty for entire timeout period
315    /// * `Err(Error)` - Deserialization error or other error
316    ///
317    /// # Examples
318    ///
319    /// ```ignore
320    /// let mut msg = Message::default();
321    /// 
322    /// match queue.fetch(&mut msg, 1000) {
323    ///     Ok(()) => println!("Received message: {:?}", msg),
324    ///     Err(_) => println!("No message available"),
325    /// }
326    /// ```
327    fn fetch(&self, buffer: &mut T, time: TickType) -> Result<()>;
328
329    /// Fetches a typed message from ISR context (non-blocking).
330    ///
331    /// ISR-safe version of `fetch()`. Returns immediately without blocking.
332    /// Must only be called from interrupt context.
333    ///
334    /// # Parameters
335    ///
336    /// * `buffer` - Mutable reference to receive the deserialized message
337    ///
338    /// # Returns
339    ///
340    /// * `Ok(())` - Message received and deserialized successfully
341    /// * `Err(Error)` - Queue is empty or deserialization failed
342    ///
343    /// # Examples
344    ///
345    /// ```ignore
346    /// // In interrupt handler
347    /// let mut msg = Message::default();
348    /// if queue.fetch_from_isr(&mut msg).is_ok() {
349    ///     // Process message
350    /// }
351    /// ```
352    fn fetch_from_isr(&self, buffer: &mut T) -> Result<()>;
353    
354    /// Posts a typed message to the queue (blocking).
355    ///
356    /// Serializes and adds a new message to the end of the queue.
357    /// Blocks the calling task if the queue is full.
358    ///
359    /// # Parameters
360    ///
361    /// * `item` - Reference to the message to serialize and send
362    /// * `time` - Maximum ticks to wait if queue is full:
363    ///   - `0`: Return immediately if full
364    ///   - `n`: Wait up to `n` ticks for space
365    ///   - `TickType::MAX`: Wait forever
366    ///
367    /// # Returns
368    ///
369    /// * `Ok(())` - Message serialized and sent successfully
370    /// * `Err(Error::Timeout)` - Queue was full for entire timeout period
371    /// * `Err(Error)` - Serialization error or other error
372    ///
373    /// # Examples
374    ///
375    /// ```ignore
376    /// let msg = Message { id: 42, value: 100 };
377    /// 
378    /// match queue.post(&msg, 1000) {
379    ///     Ok(()) => println!("Sent successfully"),
380    ///     Err(_) => println!("Failed to send"),
381    /// }
382    /// ```
383    fn post(&self, item: &T, time: TickType) -> Result<()>;
384
385    /// Posts a typed message from ISR context (non-blocking).
386    ///
387    /// ISR-safe version of `post()`. Returns immediately without blocking.
388    /// Must only be called from interrupt context.
389    ///
390    /// # Parameters
391    ///
392    /// * `item` - Reference to the message to serialize and send
393    ///
394    /// # Returns
395    ///
396    /// * `Ok(())` - Message serialized and sent successfully
397    /// * `Err(Error)` - Queue is full or serialization failed
398    ///
399    /// # Examples
400    ///
401    /// ```ignore
402    /// // In interrupt handler
403    /// let msg = Message { id: 1, value: 42 };
404    /// if queue.post_from_isr(&msg).is_err() {
405    ///     // Queue full, message dropped
406    /// }
407    /// ```
408    fn post_from_isr(&self, item: &T) -> Result<()>;
409
410    /// Deletes the queue and frees its resources.
411    ///
412    /// # Safety
413    ///
414    /// Ensure no tasks are blocked on this queue before deletion.
415    /// Calling this while tasks are waiting may cause undefined behavior.
416    ///
417    /// # Examples
418    ///
419    /// ```ignore
420    /// let mut queue = QueueStreamed::<Message>::new(10, size_of::<Message>()).unwrap();
421    /// // Use queue...
422    /// queue.delete();
423    /// ```
424    fn delete(&mut self);
425}