1use core::cell::UnsafeCell;
19use core::future::Future;
20use core::ops::{Deref, DerefMut};
21use core::pin::pin;
22
23use embassy_futures::select::{select, Either};
24use embassy_sync::blocking_mutex::raw::RawMutex;
25use embassy_time::{Duration, Timer};
26
27use crate::utils::init::{init, Init, InitDefault, UnsafeCellInit};
28use crate::utils::sync::blocking::raw::MatterRawMutex;
29use crate::utils::sync::Signal;
30
31pub trait Buffers<T>
33where
34 T: ?Sized,
35{
36 type Buffer<'a>: DerefMut<Target = T>
37 where
38 Self: 'a;
39
40 async fn get(&self) -> Option<Self::Buffer<'_>>;
47
48 fn get_immediate(&self) -> Option<Self::Buffer<'_>>;
51}
52
53impl<B, T> Buffers<T> for &B
54where
55 B: Buffers<T>,
56 T: ?Sized,
57{
58 type Buffer<'a>
59 = B::Buffer<'a>
60 where
61 Self: 'a;
62
63 fn get(&self) -> impl Future<Output = Option<Self::Buffer<'_>>> {
64 (*self).get()
65 }
66
67 fn get_immediate(&self) -> Option<Self::Buffer<'_>> {
68 (*self).get_immediate()
69 }
70}
71
72pub const DEFAULT_BUFFER_POOL_SIZE: usize = 10;
74
75pub struct PooledBuffers<T, const N: usize = DEFAULT_BUFFER_POOL_SIZE, M = MatterRawMutex> {
78 available: Signal<[bool; N], M>, pool: UnsafeCell<crate::utils::storage::Vec<T, N>>,
80 wait_timeout_ms: u32,
81}
82
83impl<T, const N: usize, M> PooledBuffers<T, N, M>
84where
85 M: RawMutex,
86{
87 #[inline(always)]
90 pub const fn new() -> Self {
91 Self::new_with_timeout(0)
92 }
93
94 #[inline(always)]
99 pub const fn new_with_timeout(wait_timeout_ms: u32) -> Self {
100 Self {
101 available: Signal::new([true; N]),
102 pool: UnsafeCell::new(crate::utils::storage::Vec::new()),
103 wait_timeout_ms,
104 }
105 }
106
107 pub fn init() -> impl Init<Self> {
110 Self::init_with_timeout(0)
111 }
112
113 pub fn init_with_timeout(wait_timeout_ms: u32) -> impl Init<Self> {
118 init!(Self {
119 available: Signal::new([true; N]),
120 pool <- UnsafeCell::init(crate::utils::storage::Vec::init()),
121 wait_timeout_ms,
122 })
123 }
124
125 fn init_buffers(pool: &UnsafeCell<crate::utils::storage::Vec<T, N>>)
126 where
127 T: InitDefault,
128 {
129 let buffers = unwrap!(unsafe { pool.get().as_mut() });
130
131 while buffers.len() < N {
132 unwrap!(buffers.push_init_unchecked(T::init_default()));
136 }
137 }
138}
139
140impl<T, const N: usize, M> Default for PooledBuffers<T, N, M>
141where
142 M: RawMutex,
143{
144 fn default() -> Self {
145 Self::new()
146 }
147}
148
149unsafe impl<T, const N: usize, M> Send for PooledBuffers<T, N, M>
150where
151 T: Send,
152 M: RawMutex + Send,
153{
154}
155
156unsafe impl<T, const N: usize, M> Sync for PooledBuffers<T, N, M>
157where
158 T: Send,
159 M: RawMutex + Send + Sync,
160{
161}
162
163impl<T, const N: usize, M> Buffers<T> for PooledBuffers<T, N, M>
164where
165 T: InitDefault,
166 M: RawMutex,
167{
168 type Buffer<'b>
169 = PooledBuffer<'b, T, N, M>
170 where
171 Self: 'b;
172
173 async fn get(&self) -> Option<Self::Buffer<'_>> {
174 if self.wait_timeout_ms > 0 {
175 let mut wait = pin!(self.available.wait(|available| {
176 Self::init_buffers(&self.pool);
178
179 if let Some(index) = available.iter().position(|a| *a) {
180 available[index] = false;
181 Some(index)
182 } else {
183 None
184 }
185 }));
186
187 let mut timeout = pin!(Timer::after(Duration::from_millis(
188 self.wait_timeout_ms as u64
189 )));
190
191 let result = select(&mut wait, &mut timeout).await;
192
193 match result {
194 Either::First(index) => {
195 let buffer = &mut unwrap!(unsafe { self.pool.get().as_mut() })[index];
196
197 Some(PooledBuffer {
198 index,
199 buffer,
200 access: self,
201 })
202 }
203 Either::Second(()) => None,
204 }
205 } else {
206 self.get_immediate()
207 }
208 }
209
210 fn get_immediate(&self) -> Option<Self::Buffer<'_>> {
211 let index = self.available.modify(|available| {
212 Self::init_buffers(&self.pool);
214
215 if let Some(index) = available.iter().position(|a| *a) {
216 available[index] = false;
217 (false, Some(index))
218 } else {
219 (false, None)
220 }
221 });
222
223 index.map(|index| {
224 let buffers = unwrap!(unsafe { self.pool.get().as_mut() });
225
226 let buffer = &mut buffers[index];
227
228 PooledBuffer {
229 index,
230 buffer,
231 access: self,
232 }
233 })
234 }
235}
236
237pub struct PooledBuffer<'a, T, const N: usize, M = MatterRawMutex>
238where
239 M: RawMutex,
240{
241 index: usize,
242 buffer: &'a mut T,
243 access: &'a PooledBuffers<T, N, M>,
244}
245
246impl<T, const N: usize, M> Drop for PooledBuffer<'_, T, N, M>
247where
248 M: RawMutex,
249{
250 fn drop(&mut self) {
251 self.access.available.modify(|available| {
252 available[self.index] = true;
253 (true, ())
254 });
255 }
256}
257
258impl<T, const N: usize, M> Deref for PooledBuffer<'_, T, N, M>
259where
260 M: RawMutex,
261{
262 type Target = T;
263
264 fn deref(&self) -> &Self::Target {
265 self.buffer.deref()
266 }
267}
268
269impl<T, const N: usize, M> DerefMut for PooledBuffer<'_, T, N, M>
270where
271 M: RawMutex,
272{
273 fn deref_mut(&mut self) -> &mut Self::Target {
274 self.buffer.deref_mut()
275 }
276}