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