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> CopperList<P> {
54 pub fn new(id: u32, msgs: P) -> Self {
56 CopperList {
57 id,
58 state: CopperListState::Initialized,
59 msgs,
60 }
61 }
62
63 pub fn change_state(&mut self, new_state: CopperListState) {
64 self.state = new_state; }
66
67 pub fn get_state(&self) -> CopperListState {
68 self.state
69 }
70}
71
72impl<P: CopperListTuple> ErasedCuStampedDataSet for CopperList<P> {
73 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
74 self.msgs.cumsgs()
75 }
76}
77
78pub struct CuListsManager<P: CopperListTuple, const N: usize> {
82 data: Box<[CopperList<P>; N]>,
83 length: usize,
84 insertion_index: usize,
85 current_cl_id: u32,
86}
87
88impl<P: CopperListTuple + fmt::Debug, const N: usize> fmt::Debug for CuListsManager<P, N> {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 f.debug_struct("CuListsManager")
91 .field("data", &self.data)
92 .field("length", &self.length)
93 .field("insertion_index", &self.insertion_index)
94 .finish()
96 }
97}
98
99pub type Iter<'a, T> = Chain<Rev<SliceIter<'a, T>>, Rev<SliceIter<'a, T>>>;
100pub type IterMut<'a, T> = Chain<Rev<SliceIterMut<'a, T>>, Rev<SliceIterMut<'a, T>>>;
101pub type AscIter<'a, T> = Chain<SliceIter<'a, T>, SliceIter<'a, T>>;
102pub type AscIterMut<'a, T> = Chain<SliceIterMut<'a, T>, SliceIterMut<'a, T>>;
103
104impl<P: CopperListTuple, const N: usize> Default for CuListsManager<P, N> {
105 fn default() -> Self {
106 Self::new()
107 }
108}
109
110impl<P: CopperListTuple, const N: usize> CuListsManager<P, N> {
111 pub fn new() -> Self {
112 let data = unsafe {
113 let layout = std::alloc::Layout::new::<[CopperList<P>; N]>();
114 let ptr = std::alloc::alloc_zeroed(layout) as *mut [CopperList<P>; N];
115 Box::from_raw(ptr)
116 };
117 CuListsManager {
118 data,
119 length: 0,
120 insertion_index: 0,
121 current_cl_id: 0,
122 }
123 }
124
125 #[inline]
128 pub fn len(&self) -> usize {
129 self.length
130 }
131
132 #[inline]
135 pub fn is_empty(&self) -> bool {
136 self.length == 0
137 }
138
139 #[inline]
142 pub fn is_full(&self) -> bool {
143 N == self.len()
144 }
145
146 #[inline]
149 pub fn clear(&mut self) {
150 self.insertion_index = 0;
151 self.length = 0;
152 }
153
154 #[inline]
155 pub fn create(&mut self) -> Option<&mut CopperList<P>> {
156 if self.is_full() {
157 return None;
158 }
159 let result = &mut self.data[self.insertion_index];
160 self.insertion_index = (self.insertion_index + 1) % N;
161 self.length += 1;
162
163 result.id = self.current_cl_id;
165 self.current_cl_id += 1;
166
167 Some(result)
168 }
169
170 #[inline]
172 pub fn peek(&self) -> Option<&CopperList<P>> {
173 if self.length == 0 {
174 return None;
175 }
176 let index = if self.insertion_index == 0 {
177 N - 1
178 } else {
179 self.insertion_index - 1
180 };
181 Some(&self.data[index])
182 }
183
184 #[inline]
185 #[allow(dead_code)]
186 fn drop_last(&mut self) {
187 if self.length == 0 {
188 return;
189 }
190 if self.insertion_index == 0 {
191 self.insertion_index = N - 1;
192 } else {
193 self.insertion_index -= 1;
194 }
195 self.length -= 1;
196 }
197
198 #[inline]
199 pub fn pop(&mut self) -> Option<&mut CopperList<P>> {
200 if self.length == 0 {
201 return None;
202 }
203 if self.insertion_index == 0 {
204 self.insertion_index = N - 1;
205 } else {
206 self.insertion_index -= 1;
207 }
208 self.length -= 1;
209 Some(&mut self.data[self.insertion_index])
210 }
211
212 #[inline]
217 pub fn iter(&self) -> Iter<CopperList<P>> {
218 let (a, b) = self.data[0..self.length].split_at(self.insertion_index);
219 a.iter().rev().chain(b.iter().rev())
220 }
221
222 #[inline]
227 pub fn iter_mut(&mut self) -> IterMut<CopperList<P>> {
228 let (a, b) = self.data.split_at_mut(self.insertion_index);
229 a.iter_mut().rev().chain(b.iter_mut().rev())
230 }
231
232 #[inline]
237 pub fn asc_iter(&self) -> AscIter<CopperList<P>> {
238 let (a, b) = self.data.split_at(self.insertion_index);
239 b.iter().chain(a.iter())
240 }
241
242 #[inline]
247 pub fn asc_iter_mut(&mut self) -> AscIterMut<CopperList<P>> {
248 let (a, b) = self.data.split_at_mut(self.insertion_index);
249 b.iter_mut().chain(a.iter_mut())
250 }
251}
252
253#[cfg(test)]
254mod tests {
255 use super::*;
256 use cu29_traits::{ErasedCuStampedData, ErasedCuStampedDataSet, MatchingTasks};
257 use serde::{Serialize, Serializer};
258
259 #[derive(Debug, Encode, Decode, PartialEq, Clone, Copy, Serialize)]
260 struct CuStampedDataSet(i32);
261
262 impl ErasedCuStampedDataSet for CuStampedDataSet {
263 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
264 Vec::new()
265 }
266 }
267
268 impl MatchingTasks for CuStampedDataSet {
269 fn get_all_task_ids() -> &'static [&'static str] {
270 &[]
271 }
272 }
273
274 #[test]
275 fn empty_queue() {
276 let q = CuListsManager::<CuStampedDataSet, 5>::new();
277
278 assert!(q.is_empty());
279 assert!(q.iter().next().is_none());
280 }
281
282 #[test]
283 fn partially_full_queue() {
284 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
285 q.create().unwrap().msgs.0 = 1;
286 q.create().unwrap().msgs.0 = 2;
287 q.create().unwrap().msgs.0 = 3;
288
289 assert!(!q.is_empty());
290 assert_eq!(q.len(), 3);
291
292 let res: Vec<i32> = q.iter().map(|x| x.msgs.0).collect();
293 assert_eq!(res, [3, 2, 1]);
294 }
295
296 #[test]
297 fn full_queue() {
298 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
299 q.create().unwrap().msgs.0 = 1;
300 q.create().unwrap().msgs.0 = 2;
301 q.create().unwrap().msgs.0 = 3;
302 q.create().unwrap().msgs.0 = 4;
303 q.create().unwrap().msgs.0 = 5;
304 assert_eq!(q.len(), 5);
305
306 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
307 assert_eq!(res, [5, 4, 3, 2, 1]);
308 }
309
310 #[test]
311 fn over_full_queue() {
312 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
313 q.create().unwrap().msgs.0 = 1;
314 q.create().unwrap().msgs.0 = 2;
315 q.create().unwrap().msgs.0 = 3;
316 q.create().unwrap().msgs.0 = 4;
317 q.create().unwrap().msgs.0 = 5;
318 assert!(q.create().is_none());
319 assert_eq!(q.len(), 5);
320
321 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
322 assert_eq!(res, [5, 4, 3, 2, 1]);
323 }
324
325 #[test]
326 fn clear() {
327 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
328 q.create().unwrap().msgs.0 = 1;
329 q.create().unwrap().msgs.0 = 2;
330 q.create().unwrap().msgs.0 = 3;
331 q.create().unwrap().msgs.0 = 4;
332 q.create().unwrap().msgs.0 = 5;
333 assert!(q.create().is_none());
334 assert_eq!(q.len(), 5);
335
336 q.clear();
337
338 assert_eq!(q.len(), 0);
339 assert!(q.iter().next().is_none());
340
341 q.create().unwrap().msgs.0 = 1;
342 q.create().unwrap().msgs.0 = 2;
343 q.create().unwrap().msgs.0 = 3;
344
345 assert_eq!(q.len(), 3);
346
347 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
348 assert_eq!(res, [3, 2, 1]);
349 }
350
351 #[test]
352 fn mutable_iterator() {
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
360 for x in q.iter_mut() {
361 x.msgs.0 *= 2;
362 }
363
364 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
365 assert_eq!(res, [10, 8, 6, 4, 2]);
366 }
367
368 #[test]
369 fn test_drop_last() {
370 let mut q = CuListsManager::<CuStampedDataSet, 5>::new();
371 q.create().unwrap().msgs.0 = 1;
372 q.create().unwrap().msgs.0 = 2;
373 q.create().unwrap().msgs.0 = 3;
374 q.create().unwrap().msgs.0 = 4;
375 q.create().unwrap().msgs.0 = 5;
376 assert_eq!(q.len(), 5);
377
378 q.drop_last();
379 assert_eq!(q.len(), 4);
380
381 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
382 assert_eq!(res, [4, 3, 2, 1]);
383 }
384
385 #[test]
386 fn test_pop() {
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 assert_eq!(q.len(), 5);
394
395 let last = q.pop().unwrap();
396 assert_eq!(last.msgs.0, 5);
397 assert_eq!(q.len(), 4);
398
399 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
400 assert_eq!(res, [4, 3, 2, 1]);
401 }
402
403 #[test]
404 fn test_peek() {
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 assert_eq!(q.len(), 5);
412
413 let last = q.peek().unwrap();
414 assert_eq!(last.msgs.0, 5);
415 assert_eq!(q.len(), 5);
416
417 let res: Vec<_> = q.iter().map(|x| x.msgs.0).collect();
418 assert_eq!(res, [5, 4, 3, 2, 1]);
419 }
420
421 #[derive(Decode, Encode, Debug, PartialEq, Clone, Copy)]
422 struct TestStruct {
423 content: [u8; 10_000_000],
424 }
425
426 impl ErasedCuStampedDataSet for TestStruct {
427 fn cumsgs(&self) -> Vec<&dyn ErasedCuStampedData> {
428 Vec::new()
429 }
430 }
431
432 impl Serialize for TestStruct {
433 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
434 where
435 S: Serializer,
436 {
437 serializer.serialize_i8(0)
438 }
439 }
440
441 impl MatchingTasks for TestStruct {
442 fn get_all_task_ids() -> &'static [&'static str] {
443 &[]
444 }
445 }
446
447 #[test]
448 fn be_sure_we_wont_stackoverflow_at_init() {
449 let _ = CuListsManager::<TestStruct, 3>::new();
450 }
451}