1use mem::ManuallyDrop;
2use mem::MaybeUninit;
3
4use crate::base::*;
5use crate::isr::*;
6use crate::prelude::v1::*;
7use crate::shim::*;
8use crate::units::*;
9
10unsafe impl<T: Sized + Send> Send for Queue<T> {}
11unsafe impl<T: Sized + Send> Sync for Queue<T> {}
12
13#[derive(Debug)]
14pub struct SendError<T> {
15 err: FreeRtosError,
16 item: T,
17}
18
19impl<T> SendError<T> {
20 pub fn error(&self) -> FreeRtosError {
21 self.err
22 }
23
24 pub fn into_item(self) -> T {
25 self.item
26 }
27}
28
29#[derive(Debug)]
31pub struct Queue<T: Sized + Send> {
32 queue: FreeRtosQueueHandle,
33 item_type: PhantomData<T>,
34}
35
36impl<T: Sized + Send> Queue<T> {
37 pub fn new(max_size: usize) -> Result<Queue<T>, FreeRtosError> {
38 let item_size = mem::size_of::<T>();
39
40 let handle = unsafe { freertos_rs_queue_create(max_size as u32, item_size as u32) };
41
42 if handle == 0 as *const _ {
43 return Err(FreeRtosError::OutOfMemory);
44 }
45
46 Ok(Queue {
47 queue: handle,
48 item_type: PhantomData,
49 })
50 }
51
52 #[inline]
58 pub unsafe fn from_raw_handle(handle: FreeRtosQueueHandle) -> Self {
59 Self {
60 queue: handle,
61 item_type: PhantomData,
62 }
63 }
64 #[inline]
65 pub fn raw_handle(&self) -> FreeRtosQueueHandle {
66 self.queue
67 }
68
69 pub fn send<D: DurationTicks>(&self, item: T, max_wait: D) -> Result<(), SendError<T>> {
71 let item = ManuallyDrop::new(item);
72 let ptr = &item as *const _ as FreeRtosVoidPtr;
73
74 unsafe {
75 if freertos_rs_queue_send(self.queue, ptr, max_wait.to_ticks()) != 0 {
76 Err(SendError {
77 err: FreeRtosError::QueueSendTimeout,
78 item: ManuallyDrop::into_inner(item),
79 })
80 } else {
81 Ok(())
82 }
83 }
84 }
85
86 pub fn send_from_isr(
88 &self,
89 context: &mut InterruptContext,
90 item: T,
91 ) -> Result<(), SendError<T>> {
92 let item = ManuallyDrop::new(item);
93 let ptr = &item as *const _ as FreeRtosVoidPtr;
94
95 unsafe {
96 if freertos_rs_queue_send_isr(self.queue, ptr, context.get_task_field_mut()) != 0 {
97 Err(SendError {
98 err: FreeRtosError::QueueFull,
99 item: ManuallyDrop::into_inner(item),
100 })
101 } else {
102 Ok(())
103 }
104 }
105 }
106
107 pub fn receive<D: DurationTicks>(&self, max_wait: D) -> Result<T, FreeRtosError> {
109 unsafe {
110 let mut buff = MaybeUninit::uninit();
113 let r = freertos_rs_queue_receive(
114 self.queue,
115 &mut buff as *mut _ as FreeRtosMutVoidPtr,
116 max_wait.to_ticks(),
117 );
118 if r == 0 {
119 return Ok(buff.assume_init());
120 } else {
121 return Err(FreeRtosError::QueueReceiveTimeout);
122 }
123 }
124 }
125
126 pub fn len(&self) -> u32 {
128 unsafe { freertos_rs_queue_messages_waiting(self.queue) }
129 }
130}
131
132impl<T: Sized + Send> Drop for Queue<T> {
133 fn drop(&mut self) {
134 unsafe {
135 freertos_rs_queue_delete(self.queue);
136 }
137 }
138}