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