1#[cfg(not(feature = "std"))]
4extern crate alloc;
5
6use alloc::boxed::Box;
7use alloc::vec::Vec;
8
9use bincode::{Decode, Encode};
10use core::fmt;
11
12use core::fmt::Display;
13use core::iter::{Chain, Rev};
14use core::slice::{Iter as SliceIter, IterMut as SliceIterMut};
15use cu29_traits::{CopperListTuple, ErasedCuStampedData, ErasedCuStampedDataSet};
16use serde_derive::{Deserialize, Serialize};
17
18const MAX_TASKS: usize = 512;
19
20#[derive(Debug, Encode, Decode, PartialEq, Clone, Copy)]
23pub struct CopperLiskMask {
24 #[allow(dead_code)]
25 mask: [u128; MAX_TASKS / 128 + 1],
26}
27
28#[derive(Debug, Encode, Decode, Serialize, Deserialize, PartialEq, Copy, Clone)]
30pub enum CopperListState {
31 Free,
32 Initialized,
33 Processing,
34 DoneProcessing,
35 QueuedForSerialization,
36 BeingSerialized,
37}
38
39impl Display for CopperListState {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 CopperListState::Free => write!(f, "Free"),
43 CopperListState::Initialized => write!(f, "Initialized"),
44 CopperListState::Processing => write!(f, "Processing"),
45 CopperListState::DoneProcessing => write!(f, "DoneProcessing"),
46 CopperListState::QueuedForSerialization => write!(f, "QueuedForSerialization"),
47 CopperListState::BeingSerialized => write!(f, "BeingSerialized"),
48 }
49 }
50}
51
52#[derive(Debug, Encode, Decode, Serialize, Deserialize)]
55pub struct CopperList<P: CopperListTuple> {
56 pub id: u64,
57 #[bincode(skip, default = "deserialized_state")]
59 #[serde(skip, default = "deserialized_state")]
60 state: CopperListState,
61 pub msgs: P, }
63
64fn deserialized_state() -> CopperListState {
65 CopperListState::BeingSerialized
66}
67
68impl<P: CopperListTuple> Default for CopperList<P> {
69 fn default() -> Self {
70 CopperList {
71 id: 0,
72 state: CopperListState::Free,
73 msgs: P::default(),
74 }
75 }
76}
77
78impl<P: CopperListTuple> CopperList<P> {
79 pub fn new(id: u64, msgs: P) -> Self {
81 CopperList {
82 id,
83 state: CopperListState::Initialized,
84 msgs,
85 }
86 }
87
88 pub fn change_state(&mut self, new_state: CopperListState) {
89 self.state = new_state; }
91
92 pub fn get_state(&self) -> CopperListState {
93 self.state
94 }
95
96 #[doc(hidden)]
99 pub fn reset_for_runtime_use(&mut self, id: u64)
100 where
101 P: CuListZeroedInit,
102 {
103 self.id = id;
104 self.state = CopperListState::Initialized;
105 self.msgs.init_zeroed();
106 }
107
108 pub(crate) unsafe fn init_in_place(dst: *mut Self)
114 where
115 P: CuListZeroedInit,
116 {
117 unsafe {
120 core::ptr::addr_of_mut!((*dst).id).write(0);
121 core::ptr::addr_of_mut!((*dst).state).write(CopperListState::Free);
122 let msgs = core::ptr::addr_of_mut!((*dst).msgs);
123 let initialized = P::init_in_place(&mut *msgs.cast::<core::mem::MaybeUninit<P>>());
124 assert!(
125 core::ptr::eq(initialized, msgs),
126 "initializer returned a different slot"
127 );
128 }
129 }
130}
131
132impl<P: CopperListTuple> ErasedCuStampedDataSet for CopperList<P> {
133 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
134 self.msgs.cumsgs()
135 }
136}
137
138pub struct CuListsManager<P: CopperListTuple, const N: usize> {
142 data: Box<[CopperList<P>; N]>,
143 length: usize,
144 insertion_index: usize,
145 current_cl_id: u64,
146}
147
148impl<P: CopperListTuple + fmt::Debug, const N: usize> fmt::Debug for CuListsManager<P, N> {
149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150 f.debug_struct("CuListsManager")
151 .field("data", &self.data)
152 .field("length", &self.length)
153 .field("insertion_index", &self.insertion_index)
154 .finish()
156 }
157}
158
159pub type Iter<'a, T> = Chain<Rev<SliceIter<'a, T>>, Rev<SliceIter<'a, T>>>;
160pub type IterMut<'a, T> = Chain<Rev<SliceIterMut<'a, T>>, Rev<SliceIterMut<'a, T>>>;
161pub type AscIter<'a, T> = Chain<SliceIter<'a, T>, SliceIter<'a, T>>;
162pub type AscIterMut<'a, T> = Chain<SliceIterMut<'a, T>, SliceIterMut<'a, T>>;
163
164pub trait CuListZeroedInit: CopperListTuple {
170 fn init_zeroed(&mut self);
172
173 #[doc(hidden)]
179 fn init_in_place(dst: &mut core::mem::MaybeUninit<Self>) -> &mut Self {
180 dst.write(Self::default())
181 }
182}
183
184impl<P: CopperListTuple + CuListZeroedInit, const N: usize> Default for CuListsManager<P, N> {
185 fn default() -> Self {
186 Self::new()
187 }
188}
189
190impl<P: CopperListTuple, const N: usize> CuListsManager<P, N> {
191 pub fn new() -> Self
192 where
193 P: CuListZeroedInit,
194 {
195 let mut slots = Vec::<CopperList<P>>::with_capacity(N);
196 for index in 0..N {
197 unsafe {
201 CopperList::init_in_place(slots.as_mut_ptr().add(index));
202 slots.set_len(index + 1);
203 }
204 }
205 let data = unsafe {
207 Box::from_raw(Box::into_raw(slots.into_boxed_slice()) as *mut [CopperList<P>; N])
208 };
209 CuListsManager {
210 data,
211 length: 0,
212 insertion_index: 0,
213 current_cl_id: 0,
214 }
215 }
216
217 #[inline]
220 pub fn len(&self) -> usize {
221 self.length
222 }
223
224 #[inline]
227 pub fn is_empty(&self) -> bool {
228 self.length == 0
229 }
230
231 #[inline]
234 pub fn is_full(&self) -> bool {
235 N == self.len()
236 }
237
238 #[inline]
241 pub fn clear(&mut self) {
242 self.insertion_index = 0;
243 self.length = 0;
244 }
245
246 #[inline]
247 pub fn create(&mut self) -> Option<&mut CopperList<P>>
248 where
249 P: CuListZeroedInit,
250 {
251 if self.is_full() {
252 return None;
253 }
254 let next_id = self.current_cl_id;
255 let result = &mut self.data[self.insertion_index];
256 self.insertion_index = (self.insertion_index + 1) % N;
257 self.length += 1;
258
259 result.reset_for_runtime_use(next_id);
261 self.current_cl_id += 1;
262
263 Some(result)
264 }
265
266 #[inline]
268 pub fn next_cl_id(&self) -> u64 {
269 self.current_cl_id
270 }
271
272 pub(crate) fn set_next_replay_id(&mut self, id: u64) {
273 debug_assert_eq!(self.length, 0);
274 self.current_cl_id = id;
275 }
276
277 #[inline]
281 pub fn last_cl_id(&self) -> u64 {
282 self.current_cl_id.saturating_sub(1)
283 }
284
285 #[inline]
287 pub fn peek(&self) -> Option<&CopperList<P>> {
288 if self.length == 0 {
289 return None;
290 }
291 let index = if self.insertion_index == 0 {
292 N - 1
293 } else {
294 self.insertion_index - 1
295 };
296 Some(&self.data[index])
297 }
298
299 #[inline]
300 #[allow(dead_code)]
301 fn drop_last(&mut self) {
302 if self.length == 0 {
303 return;
304 }
305 if self.insertion_index == 0 {
306 self.insertion_index = N - 1;
307 } else {
308 self.insertion_index -= 1;
309 }
310 self.length -= 1;
311 }
312
313 #[inline]
314 pub fn pop(&mut self) -> Option<&mut CopperList<P>> {
315 if self.length == 0 {
316 return None;
317 }
318 if self.insertion_index == 0 {
319 self.insertion_index = N - 1;
320 } else {
321 self.insertion_index -= 1;
322 }
323 self.length -= 1;
324 Some(&mut self.data[self.insertion_index])
325 }
326
327 #[inline]
332 pub fn iter(&self) -> Iter<'_, CopperList<P>> {
333 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
334 a.iter().rev().chain(b.iter().rev())
335 }
336
337 #[inline]
342 pub fn iter_mut(&mut self) -> IterMut<'_, CopperList<P>> {
343 let (a, b) = self.data[0..self.length].split_at_mut(self.insertion_index);
344 a.iter_mut().rev().chain(b.iter_mut().rev())
345 }
346
347 #[inline]
352 pub fn asc_iter(&self) -> AscIter<'_, CopperList<P>> {
353 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
354 b.iter().chain(a.iter())
355 }
356
357 #[inline]
362 pub fn asc_iter_mut(&mut self) -> AscIterMut<'_, CopperList<P>> {
363 let (a, b) = self.data[0..self.length].split_at_mut(self.insertion_index);
364 b.iter_mut().chain(a.iter_mut())
365 }
366}
367
368#[cfg(test)]
369mod tests {
370 use super::*;
371 use cu29_traits::{ErasedCuStampedData, ErasedCuStampedDataSet, MatchingTasks};
372 use serde::{Deserialize, Serialize, Serializer};
373
374 #[derive(Debug, Encode, Decode, PartialEq, Clone, Copy, Serialize, Deserialize, Default)]
375 struct CuStampedDataSet(i32);
376
377 impl ErasedCuStampedDataSet for CuStampedDataSet {
378 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
379 Vec::new()
380 }
381 }
382
383 impl MatchingTasks for CuStampedDataSet {
384 fn get_all_task_ids() -> &'static [&'static str] {
385 &[]
386 }
387 }
388
389 impl CuListZeroedInit for CuStampedDataSet {
390 fn init_zeroed(&mut self) {}
391 }
392
393 #[derive(Debug, Default, Encode, Decode, Serialize, Deserialize)]
394 struct WrongSlot;
395
396 impl ErasedCuStampedDataSet for WrongSlot {
397 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
398 Vec::new()
399 }
400 }
401
402 impl MatchingTasks for WrongSlot {
403 fn get_all_task_ids() -> &'static [&'static str] {
404 &[]
405 }
406 }
407
408 impl CuListZeroedInit for WrongSlot {
409 fn init_zeroed(&mut self) {}
410
411 fn init_in_place(_dst: &mut core::mem::MaybeUninit<Self>) -> &mut Self {
412 Box::leak(Box::new(Self))
413 }
414 }
415
416 #[test]
417 #[should_panic(expected = "initializer returned a different slot")]
418 fn rejects_initializer_returning_another_slot() {
419 let _ = CuListsManager::<WrongSlot, 1>::new();
420 }
421
422 #[test]
423 fn serialization_omits_runtime_state() {
424 let expected =
425 bincode::encode_to_vec((42u64, CuStampedDataSet(123)), bincode::config::standard())
426 .unwrap();
427 for state in [
428 CopperListState::Free,
429 CopperListState::Initialized,
430 CopperListState::Processing,
431 CopperListState::DoneProcessing,
432 CopperListState::QueuedForSerialization,
433 CopperListState::BeingSerialized,
434 ] {
435 let mut list = CopperList::new(42, CuStampedDataSet(123));
436 list.change_state(state);
437 let bytes = bincode::encode_to_vec(&list, bincode::config::standard()).unwrap();
438 assert_eq!(bytes, expected);
439 let old_bytes =
440 bincode::encode_to_vec((list.id, state, &list.msgs), bincode::config::standard())
441 .unwrap();
442 assert_eq!(old_bytes.len(), bytes.len() + 1);
443 let (decoded, used): (CopperList<CuStampedDataSet>, usize) =
444 bincode::decode_from_slice(&bytes, bincode::config::standard()).unwrap();
445 assert_eq!(decoded.id, list.id);
446 assert_eq!(decoded.msgs, list.msgs);
447 assert_eq!(decoded.get_state(), CopperListState::BeingSerialized);
448 assert_eq!(used, bytes.len());
449 let (borrowed, used): (CopperList<CuStampedDataSet>, usize) =
450 bincode::borrow_decode_from_slice(&bytes, bincode::config::standard()).unwrap();
451 assert_eq!(borrowed.get_state(), CopperListState::BeingSerialized);
452 assert_eq!(borrowed.msgs, list.msgs);
453 assert_eq!(used, bytes.len());
454 assert_eq!(list.get_state(), state);
455 #[cfg(feature = "std")]
456 {
457 let json = serde_json::to_value(&list).unwrap();
458 assert_eq!(json, serde_json::json!({"id": 42, "msgs": 123}));
459 let decoded: CopperList<CuStampedDataSet> = serde_json::from_value(json).unwrap();
460 assert_eq!(decoded.get_state(), CopperListState::BeingSerialized);
461 assert_eq!(decoded.msgs, list.msgs);
462 }
463 }
464 }
465
466 #[test]
467 fn empty_queue() {
468 let q = CuListsManager::<CuStampedDataSet, 5>::new();
469
470 assert!(q.is_empty());
471 assert!(q.iter().next().is_none());
472 assert!(q.asc_iter().next().is_none());
473 assert!(q.peek().is_none());
474 }
475
476 #[test]
477 fn partially_full_queue() {
478 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
479 q.create().unwrap().msgs.0 = 1;
480 q.create().unwrap().msgs.0 = 2;
481 q.create().unwrap().msgs.0 = 3;
482
483 assert!(!q.is_empty());
484 assert_eq!(q.len(), 3);
485
486 let res: Vec<i32> = q.iter().map(|x| x.msgs.0).collect();
487 assert_eq!(res, [3, 2, 1]);
488 }
489
490 #[test]
491 fn full_queue() {
492 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
493 q.create().unwrap().msgs.0 = 1;
494 q.create().unwrap().msgs.0 = 2;
495 q.create().unwrap().msgs.0 = 3;
496 q.create().unwrap().msgs.0 = 4;
497 q.create().unwrap().msgs.0 = 5;
498 assert_eq!(q.len(), 5);
499
500 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
501 assert_eq!(res, [5, 4, 3, 2, 1]);
502 }
503
504 #[test]
505 fn over_full_queue() {
506 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
507 q.create().unwrap().msgs.0 = 1;
508 q.create().unwrap().msgs.0 = 2;
509 q.create().unwrap().msgs.0 = 3;
510 q.create().unwrap().msgs.0 = 4;
511 q.create().unwrap().msgs.0 = 5;
512 assert!(q.create().is_none());
513 assert_eq!(q.len(), 5);
514
515 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
516 assert_eq!(res, [5, 4, 3, 2, 1]);
517 }
518
519 #[test]
520 fn clear() {
521 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
522 q.create().unwrap().msgs.0 = 1;
523 q.create().unwrap().msgs.0 = 2;
524 q.create().unwrap().msgs.0 = 3;
525 q.create().unwrap().msgs.0 = 4;
526 q.create().unwrap().msgs.0 = 5;
527 assert!(q.create().is_none());
528 assert_eq!(q.len(), 5);
529
530 q.clear();
531
532 assert_eq!(q.len(), 0);
533 assert!(q.iter().next().is_none());
534
535 q.create().unwrap().msgs.0 = 1;
536 q.create().unwrap().msgs.0 = 2;
537 q.create().unwrap().msgs.0 = 3;
538
539 assert_eq!(q.len(), 3);
540
541 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
542 assert_eq!(res, [3, 2, 1]);
543 }
544
545 #[test]
546 fn create_fresh_slot_starts_initialized_with_zeroed_payload() {
547 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
548
549 let cl = q.create().unwrap();
550 assert_eq!(cl.id, 0);
551 assert_eq!(cl.get_state(), CopperListState::Initialized);
552 assert_eq!(cl.msgs.0, 0);
553 assert_eq!(q.next_cl_id(), 1);
554 assert_eq!(q.last_cl_id(), 0);
555 }
556
557 #[test]
558 fn create_reused_slot_reinitializes_state_but_preserves_payload_storage() {
559 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
560
561 {
562 let cl = q.create().unwrap();
563 cl.msgs.0 = 41;
564 cl.change_state(CopperListState::Processing);
565 }
566
567 let popped = q.pop().unwrap();
568 assert_eq!(popped.id, 0);
569 assert_eq!(popped.get_state(), CopperListState::Processing);
570 assert_eq!(popped.msgs.0, 41);
571
572 let reused = q.create().unwrap();
573 assert_eq!(reused.id, 1);
574 assert_eq!(reused.get_state(), CopperListState::Initialized);
575 assert_eq!(reused.msgs.0, 41);
576 assert_eq!(q.next_cl_id(), 2);
577 assert_eq!(q.last_cl_id(), 1);
578 }
579
580 #[test]
581 fn mutable_iterator() {
582 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
583 q.create().unwrap().msgs.0 = 1;
584 q.create().unwrap().msgs.0 = 2;
585 q.create().unwrap().msgs.0 = 3;
586 q.create().unwrap().msgs.0 = 4;
587 q.create().unwrap().msgs.0 = 5;
588
589 for x in q.iter_mut() {
590 x.msgs.0 *= 2;
591 }
592
593 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
594 assert_eq!(res, [10, 8, 6, 4, 2]);
595 }
596
597 #[test]
598 fn mutable_iterator_non_wrapped_only_visits_active_slots() {
599 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
600 q.create().unwrap().msgs.0 = 1;
601 q.create().unwrap().msgs.0 = 2;
602 q.create().unwrap().msgs.0 = 3;
603
604 let mut visited = Vec::new();
605 for cl in q.iter_mut() {
606 visited.push(cl.id);
607 cl.msgs.0 *= 10;
608 }
609
610 assert_eq!(visited, vec![2, 1, 0]);
611 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
612 assert_eq!(res, [30, 20, 10]);
613 }
614
615 #[test]
616 fn test_drop_last() {
617 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
618 q.create().unwrap().msgs.0 = 1;
619 q.create().unwrap().msgs.0 = 2;
620 q.create().unwrap().msgs.0 = 3;
621 q.create().unwrap().msgs.0 = 4;
622 q.create().unwrap().msgs.0 = 5;
623 assert_eq!(q.len(), 5);
624
625 q.drop_last();
626 assert_eq!(q.len(), 4);
627
628 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
629 assert_eq!(res, [4, 3, 2, 1]);
630 }
631
632 #[test]
633 fn drop_last_on_empty_queue_is_a_noop() {
634 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
635
636 q.drop_last();
637
638 assert!(q.is_empty());
639 assert!(q.peek().is_none());
640 assert!(q.pop().is_none());
641 }
642
643 #[test]
644 fn drop_last_on_non_wrapped_queue_removes_most_recent_slot() {
645 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
646 q.create().unwrap().msgs.0 = 1;
647 q.create().unwrap().msgs.0 = 2;
648 q.create().unwrap().msgs.0 = 3;
649
650 q.drop_last();
651
652 assert_eq!(q.len(), 2);
653 assert_eq!(q.peek().unwrap().msgs.0, 2);
654 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
655 assert_eq!(res, [2, 1]);
656 }
657
658 #[test]
659 fn test_pop() {
660 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
661 q.create().unwrap().msgs.0 = 1;
662 q.create().unwrap().msgs.0 = 2;
663 q.create().unwrap().msgs.0 = 3;
664 q.create().unwrap().msgs.0 = 4;
665 q.create().unwrap().msgs.0 = 5;
666 assert_eq!(q.len(), 5);
667
668 let last = q.pop().unwrap();
669 assert_eq!(last.msgs.0, 5);
670 assert_eq!(q.len(), 4);
671
672 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
673 assert_eq!(res, [4, 3, 2, 1]);
674 }
675
676 #[test]
677 fn pop_on_empty_queue_returns_none() {
678 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
679
680 assert!(q.pop().is_none());
681 assert!(q.is_empty());
682 }
683
684 #[test]
685 fn test_peek() {
686 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
687 q.create().unwrap().msgs.0 = 1;
688 q.create().unwrap().msgs.0 = 2;
689 q.create().unwrap().msgs.0 = 3;
690 q.create().unwrap().msgs.0 = 4;
691 q.create().unwrap().msgs.0 = 5;
692 assert_eq!(q.len(), 5);
693
694 let last = q.peek().unwrap();
695 assert_eq!(last.msgs.0, 5);
696 assert_eq!(q.len(), 5);
697
698 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
699 assert_eq!(res, [5, 4, 3, 2, 1]);
700 }
701
702 #[test]
703 fn peek_on_empty_queue_returns_none() {
704 let q = CuListsManager::<CuStampedDataSet, 5>::new();
705
706 assert!(q.peek().is_none());
707 }
708
709 #[test]
710 fn next_and_last_cl_id_track_assigned_ids() {
711 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
712
713 assert_eq!(q.next_cl_id(), 0);
715 assert_eq!(q.last_cl_id(), 0);
716
717 let cl0 = q.create().unwrap();
718 assert_eq!(cl0.id, 0);
719 assert_eq!(q.next_cl_id(), 1);
720 assert_eq!(q.last_cl_id(), 0);
721
722 let cl1 = q.create().unwrap();
723 assert_eq!(cl1.id, 1);
724 assert_eq!(q.next_cl_id(), 2);
725 assert_eq!(q.last_cl_id(), 1);
726
727 let _ = q.pop().unwrap();
728 let cl2 = q.create().unwrap();
729 assert_eq!(cl2.id, 2);
730 assert_eq!(q.next_cl_id(), 3);
731 assert_eq!(q.last_cl_id(), 2);
732 }
733
734 #[test]
735 fn asc_iter_non_wrapped_returns_oldest_to_newest_without_free_slots() {
736 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
737 q.create().unwrap().msgs.0 = 10;
738 q.create().unwrap().msgs.0 = 20;
739 q.create().unwrap().msgs.0 = 30;
740
741 let res: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
742 assert_eq!(res, [10, 20, 30]);
743 }
744
745 #[test]
746 fn asc_iter_mut_non_wrapped_only_visits_active_slots_in_oldest_first_order() {
747 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
748 q.create().unwrap().msgs.0 = 10;
749 q.create().unwrap().msgs.0 = 20;
750 q.create().unwrap().msgs.0 = 30;
751
752 let mut visited = Vec::new();
753 for (offset, cl) in q.asc_iter_mut().enumerate() {
754 visited.push(cl.id);
755 cl.msgs.0 += offset as i32;
756 }
757
758 assert_eq!(visited, vec![0, 1, 2]);
759 let res: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
760 assert_eq!(res, [10, 21, 32]);
761 }
762
763 #[test]
764 fn asc_iter_wrapped_layout_tracks_reused_slots_in_ascending_order() {
765 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
766 for value in 1..=5 {
767 q.create().unwrap().msgs.0 = value;
768 }
769 assert_eq!(q.pop().unwrap().msgs.0, 5);
770 assert_eq!(q.pop().unwrap().msgs.0, 4);
771 q.create().unwrap().msgs.0 = 6;
772 q.create().unwrap().msgs.0 = 7;
773
774 let desc: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
775 assert_eq!(desc, [7, 6, 3, 2, 1]);
776
777 let asc: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
778 assert_eq!(asc, [1, 2, 3, 6, 7]);
779 }
780
781 #[test]
782 fn asc_iter_mut_wrapped_layout_updates_oldest_to_newest_order() {
783 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
784 for value in 1..=5 {
785 q.create().unwrap().msgs.0 = value;
786 }
787 let _ = q.pop().unwrap();
788 let _ = q.pop().unwrap();
789 q.create().unwrap().msgs.0 = 6;
790 q.create().unwrap().msgs.0 = 7;
791
792 let mut visited = Vec::new();
793 for (offset, cl) in q.asc_iter_mut().enumerate() {
794 visited.push(cl.id);
795 cl.msgs.0 += offset as i32;
796 }
797
798 assert_eq!(visited, vec![0, 1, 2, 5, 6]);
799 let asc: Vec<_> = q.asc_iter().map(|x| x.msgs.0).collect();
800 assert_eq!(asc, [1, 3, 5, 9, 11]);
801 }
802
803 #[derive(Decode, Encode, Debug, PartialEq, Clone, Copy)]
804 struct TestStruct {
805 content: [u8; 10_000_000],
806 }
807
808 impl Default for TestStruct {
809 fn default() -> Self {
810 TestStruct {
811 content: [0; 10_000_000],
812 }
813 }
814 }
815
816 impl ErasedCuStampedDataSet for TestStruct {
817 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
818 Vec::new()
819 }
820 }
821
822 impl Serialize for TestStruct {
823 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
824 where
825 S: Serializer,
826 {
827 serializer.serialize_i8(0)
828 }
829 }
830
831 impl MatchingTasks for TestStruct {
832 fn get_all_task_ids() -> &'static [&'static str] {
833 &[]
834 }
835 }
836
837 impl CuListZeroedInit for TestStruct {
838 fn init_zeroed(&mut self) {}
839
840 fn init_in_place(dst: &mut core::mem::MaybeUninit<Self>) -> &mut Self {
841 unsafe {
843 dst.as_mut_ptr().write_bytes(0, 1);
844 dst.assume_init_mut()
845 }
846 }
847 }
848
849 #[test]
850 fn be_sure_we_wont_stackoverflow_at_init() {
851 let _ = CuListsManager::<TestStruct, 3>::new();
852 }
853}