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}