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::{Deserialize, 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, Deserialize, 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, Deserialize)]
53pub struct CopperList<P: CopperListTuple> {
54 pub id: u64,
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: u64, 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: u64,
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 {
141 let layout = Layout::new::<[CopperList<P>; N]>();
142 let ptr = alloc_zeroed(layout) as *mut [CopperList<P>; N];
143 if ptr.is_null() {
144 handle_alloc_error(layout);
145 }
146 Box::from_raw(ptr)
147 };
148 let mut manager = CuListsManager {
149 data,
150 length: 0,
151 insertion_index: 0,
152 current_cl_id: 0,
153 };
154
155 for cl in manager.data.iter_mut() {
156 cl.msgs.init_zeroed();
157 }
158
159 manager
160 }
161
162 #[inline]
165 pub fn len(&self) -> usize {
166 self.length
167 }
168
169 #[inline]
172 pub fn is_empty(&self) -> bool {
173 self.length == 0
174 }
175
176 #[inline]
179 pub fn is_full(&self) -> bool {
180 N == self.len()
181 }
182
183 #[inline]
186 pub fn clear(&mut self) {
187 self.insertion_index = 0;
188 self.length = 0;
189 }
190
191 #[inline]
192 pub fn create(&mut self) -> Option<&mut CopperList<P>> {
193 if self.is_full() {
194 return None;
195 }
196 let result = &mut self.data[self.insertion_index];
197 self.insertion_index = (self.insertion_index + 1) % N;
198 self.length += 1;
199
200 result.id = self.current_cl_id;
202 self.current_cl_id += 1;
203
204 Some(result)
205 }
206
207 #[inline]
209 pub fn next_cl_id(&self) -> u64 {
210 self.current_cl_id
211 }
212
213 #[inline]
217 pub fn last_cl_id(&self) -> u64 {
218 self.current_cl_id.saturating_sub(1)
219 }
220
221 #[inline]
223 pub fn peek(&self) -> Option<&CopperList<P>> {
224 if self.length == 0 {
225 return None;
226 }
227 let index = if self.insertion_index == 0 {
228 N - 1
229 } else {
230 self.insertion_index - 1
231 };
232 Some(&self.data[index])
233 }
234
235 #[inline]
236 #[allow(dead_code)]
237 fn drop_last(&mut self) {
238 if self.length == 0 {
239 return;
240 }
241 if self.insertion_index == 0 {
242 self.insertion_index = N - 1;
243 } else {
244 self.insertion_index -= 1;
245 }
246 self.length -= 1;
247 }
248
249 #[inline]
250 pub fn pop(&mut self) -> Option<&mut CopperList<P>> {
251 if self.length == 0 {
252 return None;
253 }
254 if self.insertion_index == 0 {
255 self.insertion_index = N - 1;
256 } else {
257 self.insertion_index -= 1;
258 }
259 self.length -= 1;
260 Some(&mut self.data[self.insertion_index])
261 }
262
263 #[inline]
268 pub fn iter(&self) -> Iter<'_, CopperList<P>> {
269 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
270 a.iter().rev().chain(b.iter().rev())
271 }
272
273 #[inline]
278 pub fn iter_mut(&mut self) -> IterMut<'_, CopperList<P>> {
279 let (a, b) = self.data.split_at_mut(self.insertion_index);
280 a.iter_mut().rev().chain(b.iter_mut().rev())
281 }
282
283 #[inline]
288 pub fn asc_iter(&self) -> AscIter<'_, CopperList<P>> {
289 let (a, b) = self.data.split_at(self.insertion_index);
290 b.iter().chain(a.iter())
291 }
292
293 #[inline]
298 pub fn asc_iter_mut(&mut self) -> AscIterMut<'_, CopperList<P>> {
299 let (a, b) = self.data.split_at_mut(self.insertion_index);
300 b.iter_mut().chain(a.iter_mut())
301 }
302}
303
304#[cfg(test)]
305mod tests {
306 use super::*;
307 use cu29_traits::{ErasedCuStampedData, ErasedCuStampedDataSet, MatchingTasks};
308 use serde::{Deserialize, Serialize, Serializer};
309
310 #[derive(Debug, Encode, Decode, PartialEq, Clone, Copy, Serialize, Deserialize, Default)]
311 struct CuStampedDataSet(i32);
312
313 impl ErasedCuStampedDataSet for CuStampedDataSet {
314 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
315 Vec::new()
316 }
317 }
318
319 impl MatchingTasks for CuStampedDataSet {
320 fn get_all_task_ids() -> &'static [&'static str] {
321 &[]
322 }
323 }
324
325 impl CuListZeroedInit for CuStampedDataSet {
326 fn init_zeroed(&mut self) {}
327 }
328
329 #[test]
330 fn empty_queue() {
331 let q = CuListsManager::<CuStampedDataSet, 5>::new();
332
333 assert!(q.is_empty());
334 assert!(q.iter().next().is_none());
335 }
336
337 #[test]
338 fn partially_full_queue() {
339 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
340 q.create().unwrap().msgs.0 = 1;
341 q.create().unwrap().msgs.0 = 2;
342 q.create().unwrap().msgs.0 = 3;
343
344 assert!(!q.is_empty());
345 assert_eq!(q.len(), 3);
346
347 let res: Vec<i32> = q.iter().map(|x| x.msgs.0).collect();
348 assert_eq!(res, [3, 2, 1]);
349 }
350
351 #[test]
352 fn full_queue() {
353 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
354 q.create().unwrap().msgs.0 = 1;
355 q.create().unwrap().msgs.0 = 2;
356 q.create().unwrap().msgs.0 = 3;
357 q.create().unwrap().msgs.0 = 4;
358 q.create().unwrap().msgs.0 = 5;
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 over_full_queue() {
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 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
377 assert_eq!(res, [5, 4, 3, 2, 1]);
378 }
379
380 #[test]
381 fn clear() {
382 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
383 q.create().unwrap().msgs.0 = 1;
384 q.create().unwrap().msgs.0 = 2;
385 q.create().unwrap().msgs.0 = 3;
386 q.create().unwrap().msgs.0 = 4;
387 q.create().unwrap().msgs.0 = 5;
388 assert!(q.create().is_none());
389 assert_eq!(q.len(), 5);
390
391 q.clear();
392
393 assert_eq!(q.len(), 0);
394 assert!(q.iter().next().is_none());
395
396 q.create().unwrap().msgs.0 = 1;
397 q.create().unwrap().msgs.0 = 2;
398 q.create().unwrap().msgs.0 = 3;
399
400 assert_eq!(q.len(), 3);
401
402 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
403 assert_eq!(res, [3, 2, 1]);
404 }
405
406 #[test]
407 fn mutable_iterator() {
408 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
409 q.create().unwrap().msgs.0 = 1;
410 q.create().unwrap().msgs.0 = 2;
411 q.create().unwrap().msgs.0 = 3;
412 q.create().unwrap().msgs.0 = 4;
413 q.create().unwrap().msgs.0 = 5;
414
415 for x in q.iter_mut() {
416 x.msgs.0 *= 2;
417 }
418
419 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
420 assert_eq!(res, [10, 8, 6, 4, 2]);
421 }
422
423 #[test]
424 fn test_drop_last() {
425 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
426 q.create().unwrap().msgs.0 = 1;
427 q.create().unwrap().msgs.0 = 2;
428 q.create().unwrap().msgs.0 = 3;
429 q.create().unwrap().msgs.0 = 4;
430 q.create().unwrap().msgs.0 = 5;
431 assert_eq!(q.len(), 5);
432
433 q.drop_last();
434 assert_eq!(q.len(), 4);
435
436 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
437 assert_eq!(res, [4, 3, 2, 1]);
438 }
439
440 #[test]
441 fn test_pop() {
442 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
443 q.create().unwrap().msgs.0 = 1;
444 q.create().unwrap().msgs.0 = 2;
445 q.create().unwrap().msgs.0 = 3;
446 q.create().unwrap().msgs.0 = 4;
447 q.create().unwrap().msgs.0 = 5;
448 assert_eq!(q.len(), 5);
449
450 let last = q.pop().unwrap();
451 assert_eq!(last.msgs.0, 5);
452 assert_eq!(q.len(), 4);
453
454 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
455 assert_eq!(res, [4, 3, 2, 1]);
456 }
457
458 #[test]
459 fn test_peek() {
460 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
461 q.create().unwrap().msgs.0 = 1;
462 q.create().unwrap().msgs.0 = 2;
463 q.create().unwrap().msgs.0 = 3;
464 q.create().unwrap().msgs.0 = 4;
465 q.create().unwrap().msgs.0 = 5;
466 assert_eq!(q.len(), 5);
467
468 let last = q.peek().unwrap();
469 assert_eq!(last.msgs.0, 5);
470 assert_eq!(q.len(), 5);
471
472 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
473 assert_eq!(res, [5, 4, 3, 2, 1]);
474 }
475
476 #[test]
477 fn next_and_last_cl_id_track_assigned_ids() {
478 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
479
480 assert_eq!(q.next_cl_id(), 0);
482 assert_eq!(q.last_cl_id(), 0);
483
484 let cl0 = q.create().unwrap();
485 assert_eq!(cl0.id, 0);
486 assert_eq!(q.next_cl_id(), 1);
487 assert_eq!(q.last_cl_id(), 0);
488
489 let cl1 = q.create().unwrap();
490 assert_eq!(cl1.id, 1);
491 assert_eq!(q.next_cl_id(), 2);
492 assert_eq!(q.last_cl_id(), 1);
493 }
494
495 #[derive(Decode, Encode, Debug, PartialEq, Clone, Copy)]
496 struct TestStruct {
497 content: [u8; 10_000_000],
498 }
499
500 impl Default for TestStruct {
501 fn default() -> Self {
502 TestStruct {
503 content: [0; 10_000_000],
504 }
505 }
506 }
507
508 impl ErasedCuStampedDataSet for TestStruct {
509 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
510 Vec::new()
511 }
512 }
513
514 impl Serialize for TestStruct {
515 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
516 where
517 S: Serializer,
518 {
519 serializer.serialize_i8(0)
520 }
521 }
522
523 impl MatchingTasks for TestStruct {
524 fn get_all_task_ids() -> &'static [&'static str] {
525 &[]
526 }
527 }
528
529 impl CuListZeroedInit for TestStruct {
530 fn init_zeroed(&mut self) {}
531 }
532
533 #[test]
534 fn be_sure_we_wont_stackoverflow_at_init() {
535 let _ = CuListsManager::<TestStruct, 3>::new();
536 }
537}