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}