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}