sim_lib_stream_host/
ring.rs1use sim_kernel::{Error, Result};
4use sim_lib_stream_core::StreamStats;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum ProcessRingPush<T> {
9 Accepted,
11 DroppedNewest(T),
13 Closed(T),
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub struct ProcessRingSnapshot {
20 capacity: usize,
21 len: usize,
22 allocated_slots: usize,
23}
24
25#[derive(Debug)]
37pub struct ProcessSharedRing<T> {
38 slots: Vec<Option<T>>,
39 head: usize,
40 len: usize,
41 closed: bool,
42 stats: StreamStats,
43}
44
45impl<T> ProcessSharedRing<T> {
46 pub fn with_capacity(capacity: usize) -> Result<Self> {
62 if capacity == 0 {
63 return Err(Error::Eval(
64 "process ring capacity must be greater than zero".to_owned(),
65 ));
66 }
67 let slots = std::iter::repeat_with(|| None).take(capacity).collect();
68 Ok(Self {
69 slots,
70 head: 0,
71 len: 0,
72 closed: false,
73 stats: StreamStats::default(),
74 })
75 }
76
77 pub fn try_push(&mut self, item: T) -> ProcessRingPush<T> {
80 self.stats.pushed = self.stats.pushed.saturating_add(1);
81 if self.closed {
82 self.stats.closed = true;
83 return ProcessRingPush::Closed(item);
84 }
85 if self.len == self.capacity() {
86 self.stats.dropped_newest = self.stats.dropped_newest.saturating_add(1);
87 return ProcessRingPush::DroppedNewest(item);
88 }
89 let tail = (self.head + self.len) % self.capacity();
90 self.slots[tail] = Some(item);
91 self.len += 1;
92 self.stats.accepted = self.stats.accepted.saturating_add(1);
93 ProcessRingPush::Accepted
94 }
95
96 pub fn try_pop(&mut self) -> Option<T> {
98 if self.len == 0 {
99 return None;
100 }
101 let item = self.slots[self.head].take();
102 self.head = (self.head + 1) % self.capacity();
103 self.len -= 1;
104 if item.is_some() {
105 self.stats.yielded = self.stats.yielded.saturating_add(1);
106 }
107 item
108 }
109
110 pub fn close(&mut self) {
112 self.closed = true;
113 self.stats.closed = true;
114 }
115
116 pub fn cancel(&mut self) {
118 while self.try_pop().is_some() {}
119 self.closed = true;
120 self.stats.closed = true;
121 self.stats.cancelled = true;
122 }
123
124 pub fn len(&self) -> usize {
126 self.len
127 }
128
129 pub fn is_empty(&self) -> bool {
131 self.len == 0
132 }
133
134 pub fn capacity(&self) -> usize {
136 self.slots.len()
137 }
138
139 pub fn allocated_slots(&self) -> usize {
141 self.slots.capacity()
142 }
143
144 pub fn is_closed(&self) -> bool {
146 self.closed
147 }
148
149 pub fn snapshot(&self) -> ProcessRingSnapshot {
151 ProcessRingSnapshot {
152 capacity: self.capacity(),
153 len: self.len,
154 allocated_slots: self.allocated_slots(),
155 }
156 }
157
158 pub fn stats(&self) -> StreamStats {
160 self.stats.clone()
161 }
162}
163
164impl ProcessRingSnapshot {
165 pub fn capacity(self) -> usize {
167 self.capacity
168 }
169
170 pub fn len(self) -> usize {
172 self.len
173 }
174
175 pub fn is_empty(self) -> bool {
177 self.len == 0
178 }
179
180 pub fn allocated_slots(self) -> usize {
182 self.allocated_slots
183 }
184}