1#[cfg(not(feature = "std"))]
4extern crate alloc;
5
6use alloc::alloc::{alloc_zeroed, handle_alloc_error};
7use alloc::boxed::Box;
8use alloc::vec::Vec;
9use core::alloc::Layout;
10
11use bincode::{Decode, Encode};
12use core::fmt;
13
14use core::fmt::Display;
15use core::iter::{Chain, Rev};
16use core::slice::{Iter as SliceIter, IterMut as SliceIterMut};
17use cu29_traits::{CopperListTuple, ErasedCuStampedData, ErasedCuStampedDataSet};
18use serde_derive::Serialize;
19
20const MAX_TASKS: usize = 512;
21
22#[derive(Debug, Encode, Decode, PartialEq, Clone, Copy)]
25pub struct CopperLiskMask {
26 #[allow(dead_code)]
27 mask: [u128; MAX_TASKS / 128 + 1],
28}
29
30#[derive(Debug, Encode, Decode, Serialize, PartialEq, Copy, Clone)]
32pub enum CopperListState {
33 Free,
34 Initialized,
35 Processing,
36 DoneProcessing,
37 BeingSerialized,
38}
39
40impl Display for CopperListState {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 CopperListState::Free => write!(f, "Free"),
44 CopperListState::Initialized => write!(f, "Initialized"),
45 CopperListState::Processing => write!(f, "Processing"),
46 CopperListState::DoneProcessing => write!(f, "DoneProcessing"),
47 CopperListState::BeingSerialized => write!(f, "BeingSerialized"),
48 }
49 }
50}
51
52#[derive(Debug, Encode, Decode, Serialize)]
53pub struct CopperList<P: CopperListTuple> {
54 pub id: u32,
55 state: CopperListState,
56 pub msgs: P, }
58
59impl<P: CopperListTuple> Default for CopperList<P> {
60 fn default() -> Self {
61 CopperList {
62 id: 0,
63 state: CopperListState::Free,
64 msgs: P::default(),
65 }
66 }
67}
68
69impl<P: CopperListTuple> CopperList<P> {
70 pub fn new(id: u32, msgs: P) -> Self {
72 CopperList {
73 id,
74 state: CopperListState::Initialized,
75 msgs,
76 }
77 }
78
79 pub fn change_state(&mut self, new_state: CopperListState) {
80 self.state = new_state; }
82
83 pub fn get_state(&self) -> CopperListState {
84 self.state
85 }
86}
87
88impl<P: CopperListTuple> ErasedCuStampedDataSet for CopperList<P> {
89 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
90 self.msgs.cumsgs()
91 }
92}
93
94pub struct CuListsManager<P: CopperListTuple, const N: usize> {
98 data: Box<[CopperList<P>; N]>,
99 length: usize,
100 insertion_index: usize,
101 current_cl_id: u32,
102}
103
104impl<P: CopperListTuple + fmt::Debug, const N: usize> fmt::Debug for CuListsManager<P, N> {
105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106 f.debug_struct("CuListsManager")
107 .field("data", &self.data)
108 .field("length", &self.length)
109 .field("insertion_index", &self.insertion_index)
110 .finish()
112 }
113}
114
115pub type Iter<'a, T> = Chain<Rev<SliceIter<'a, T>>, Rev<SliceIter<'a, T>>>;
116pub type IterMut<'a, T> = Chain<Rev<SliceIterMut<'a, T>>, Rev<SliceIterMut<'a, T>>>;
117pub type AscIter<'a, T> = Chain<SliceIter<'a, T>, SliceIter<'a, T>>;
118pub type AscIterMut<'a, T> = Chain<SliceIterMut<'a, T>, SliceIterMut<'a, T>>;
119
120pub trait CuListZeroedInit: CopperListTuple {
123 fn init_zeroed(&mut self);
126}
127
128impl<P: CopperListTuple + CuListZeroedInit, const N: usize> Default for CuListsManager<P, N> {
129 fn default() -> Self {
130 Self::new()
131 }
132}
133
134impl<P: CopperListTuple, const N: usize> CuListsManager<P, N> {
135 pub fn new() -> Self
136 where
137 P: CuListZeroedInit,
138 {
139 let data = unsafe {
140 let layout = Layout::new::<[CopperList<P>; N]>();
141 let ptr = alloc_zeroed(layout) as *mut [CopperList<P>; N];
142 if ptr.is_null() {
143 handle_alloc_error(layout);
144 }
145 Box::from_raw(ptr)
146 };
147 let mut manager = CuListsManager {
148 data,
149 length: 0,
150 insertion_index: 0,
151 current_cl_id: 0,
152 };
153
154 for cl in manager.data.iter_mut() {
155 cl.msgs.init_zeroed();
156 }
157
158 manager
159 }
160
161 #[inline]
164 pub fn len(&self) -> usize {
165 self.length
166 }
167
168 #[inline]
171 pub fn is_empty(&self) -> bool {
172 self.length == 0
173 }
174
175 #[inline]
178 pub fn is_full(&self) -> bool {
179 N == self.len()
180 }
181
182 #[inline]
185 pub fn clear(&mut self) {
186 self.insertion_index = 0;
187 self.length = 0;
188 }
189
190 #[inline]
191 pub fn create(&mut self) -> Option<&mut CopperList<P>> {
192 if self.is_full() {
193 return None;
194 }
195 let result = &mut self.data[self.insertion_index];
196 self.insertion_index = (self.insertion_index + 1) % N;
197 self.length += 1;
198
199 result.id = self.current_cl_id;
201 self.current_cl_id += 1;
202
203 Some(result)
204 }
205
206 #[inline]
208 pub fn peek(&self) -> Option<&CopperList<P>> {
209 if self.length == 0 {
210 return None;
211 }
212 let index = if self.insertion_index == 0 {
213 N - 1
214 } else {
215 self.insertion_index - 1
216 };
217 Some(&self.data[index])
218 }
219
220 #[inline]
221 #[allow(dead_code)]
222 fn drop_last(&mut self) {
223 if self.length == 0 {
224 return;
225 }
226 if self.insertion_index == 0 {
227 self.insertion_index = N - 1;
228 } else {
229 self.insertion_index -= 1;
230 }
231 self.length -= 1;
232 }
233
234 #[inline]
235 pub fn pop(&mut self) -> Option<&mut CopperList<P>> {
236 if self.length == 0 {
237 return None;
238 }
239 if self.insertion_index == 0 {
240 self.insertion_index = N - 1;
241 } else {
242 self.insertion_index -= 1;
243 }
244 self.length -= 1;
245 Some(&mut self.data[self.insertion_index])
246 }
247
248 #[inline]
253 pub fn iter(&self) -> Iter<'_, CopperList<P>> {
254 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
255 a.iter().rev().chain(b.iter().rev())
256 }
257
258 #[inline]
263 pub fn iter_mut(&mut self) -> IterMut<'_, CopperList<P>> {
264 let (a, b) = self.data.split_at_mut(self.insertion_index);
265 a.iter_mut().rev().chain(b.iter_mut().rev())
266 }
267
268 #[inline]
273 pub fn asc_iter(&self) -> AscIter<'_, CopperList<P>> {
274 let (a, b) = self.data.split_at(self.insertion_index);
275 b.iter().chain(a.iter())
276 }
277
278 #[inline]
283 pub fn asc_iter_mut(&mut self) -> AscIterMut<'_, CopperList<P>> {
284 let (a, b) = self.data.split_at_mut(self.insertion_index);
285 b.iter_mut().chain(a.iter_mut())
286 }
287}
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292 use cu29_traits::{ErasedCuStampedData, ErasedCuStampedDataSet, MatchingTasks};
293 use serde::{Serialize, Serializer};
294
295 #[derive(Debug, Encode, Decode, PartialEq, Clone, Copy, Serialize, Default)]
296 struct CuStampedDataSet(i32);
297
298 impl ErasedCuStampedDataSet for CuStampedDataSet {
299 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
300 Vec::new()
301 }
302 }
303
304 impl MatchingTasks for CuStampedDataSet {
305 fn get_all_task_ids() -> &'static [&'static str] {
306 &[]
307 }
308 }
309
310 impl CuListZeroedInit for CuStampedDataSet {
311 fn init_zeroed(&mut self) {}
312 }
313
314 #[test]
315 fn empty_queue() {
316 let q = CuListsManager::<CuStampedDataSet, 5>::new();
317
318 assert!(q.is_empty());
319 assert!(q.iter().next().is_none());
320 }
321
322 #[test]
323 fn partially_full_queue() {
324 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
325 q.create().unwrap().msgs.0 = 1;
326 q.create().unwrap().msgs.0 = 2;
327 q.create().unwrap().msgs.0 = 3;
328
329 assert!(!q.is_empty());
330 assert_eq!(q.len(), 3);
331
332 let res: Vec<i32> = q.iter().map(|x| x.msgs.0).collect();
333 assert_eq!(res, [3, 2, 1]);
334 }
335
336 #[test]
337 fn full_queue() {
338 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
339 q.create().unwrap().msgs.0 = 1;
340 q.create().unwrap().msgs.0 = 2;
341 q.create().unwrap().msgs.0 = 3;
342 q.create().unwrap().msgs.0 = 4;
343 q.create().unwrap().msgs.0 = 5;
344 assert_eq!(q.len(), 5);
345
346 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
347 assert_eq!(res, [5, 4, 3, 2, 1]);
348 }
349
350 #[test]
351 fn over_full_queue() {
352 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
353 q.create().unwrap().msgs.0 = 1;
354 q.create().unwrap().msgs.0 = 2;
355 q.create().unwrap().msgs.0 = 3;
356 q.create().unwrap().msgs.0 = 4;
357 q.create().unwrap().msgs.0 = 5;
358 assert!(q.create().is_none());
359 assert_eq!(q.len(), 5);
360
361 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
362 assert_eq!(res, [5, 4, 3, 2, 1]);
363 }
364
365 #[test]
366 fn clear() {
367 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
368 q.create().unwrap().msgs.0 = 1;
369 q.create().unwrap().msgs.0 = 2;
370 q.create().unwrap().msgs.0 = 3;
371 q.create().unwrap().msgs.0 = 4;
372 q.create().unwrap().msgs.0 = 5;
373 assert!(q.create().is_none());
374 assert_eq!(q.len(), 5);
375
376 q.clear();
377
378 assert_eq!(q.len(), 0);
379 assert!(q.iter().next().is_none());
380
381 q.create().unwrap().msgs.0 = 1;
382 q.create().unwrap().msgs.0 = 2;
383 q.create().unwrap().msgs.0 = 3;
384
385 assert_eq!(q.len(), 3);
386
387 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
388 assert_eq!(res, [3, 2, 1]);
389 }
390
391 #[test]
392 fn mutable_iterator() {
393 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
394 q.create().unwrap().msgs.0 = 1;
395 q.create().unwrap().msgs.0 = 2;
396 q.create().unwrap().msgs.0 = 3;
397 q.create().unwrap().msgs.0 = 4;
398 q.create().unwrap().msgs.0 = 5;
399
400 for x in q.iter_mut() {
401 x.msgs.0 *= 2;
402 }
403
404 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
405 assert_eq!(res, [10, 8, 6, 4, 2]);
406 }
407
408 #[test]
409 fn test_drop_last() {
410 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
411 q.create().unwrap().msgs.0 = 1;
412 q.create().unwrap().msgs.0 = 2;
413 q.create().unwrap().msgs.0 = 3;
414 q.create().unwrap().msgs.0 = 4;
415 q.create().unwrap().msgs.0 = 5;
416 assert_eq!(q.len(), 5);
417
418 q.drop_last();
419 assert_eq!(q.len(), 4);
420
421 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
422 assert_eq!(res, [4, 3, 2, 1]);
423 }
424
425 #[test]
426 fn test_pop() {
427 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
428 q.create().unwrap().msgs.0 = 1;
429 q.create().unwrap().msgs.0 = 2;
430 q.create().unwrap().msgs.0 = 3;
431 q.create().unwrap().msgs.0 = 4;
432 q.create().unwrap().msgs.0 = 5;
433 assert_eq!(q.len(), 5);
434
435 let last = q.pop().unwrap();
436 assert_eq!(last.msgs.0, 5);
437 assert_eq!(q.len(), 4);
438
439 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
440 assert_eq!(res, [4, 3, 2, 1]);
441 }
442
443 #[test]
444 fn test_peek() {
445 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
446 q.create().unwrap().msgs.0 = 1;
447 q.create().unwrap().msgs.0 = 2;
448 q.create().unwrap().msgs.0 = 3;
449 q.create().unwrap().msgs.0 = 4;
450 q.create().unwrap().msgs.0 = 5;
451 assert_eq!(q.len(), 5);
452
453 let last = q.peek().unwrap();
454 assert_eq!(last.msgs.0, 5);
455 assert_eq!(q.len(), 5);
456
457 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
458 assert_eq!(res, [5, 4, 3, 2, 1]);
459 }
460
461 #[derive(Decode, Encode, Debug, PartialEq, Clone, Copy)]
462 struct TestStruct {
463 content: [u8; 10_000_000],
464 }
465
466 impl Default for TestStruct {
467 fn default() -> Self {
468 TestStruct {
469 content: [0; 10_000_000],
470 }
471 }
472 }
473
474 impl ErasedCuStampedDataSet for TestStruct {
475 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
476 Vec::new()
477 }
478 }
479
480 impl Serialize for TestStruct {
481 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
482 where
483 S: Serializer,
484 {
485 serializer.serialize_i8(0)
486 }
487 }
488
489 impl MatchingTasks for TestStruct {
490 fn get_all_task_ids() -> &'static [&'static str] {
491 &[]
492 }
493 }
494
495 impl CuListZeroedInit for TestStruct {
496 fn init_zeroed(&mut self) {}
497 }
498
499 #[test]
500 fn be_sure_we_wont_stackoverflow_at_init() {
501 let _ = CuListsManager::<TestStruct, 3>::new();
502 }
503}