1use superfluid_abi::{RingRef, TokenRef};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
6pub enum RingError {
7 #[error("unknown ring id {0}")]
8 UnknownRing(u32),
9 #[error("stale generation (ref {reference}, current {current})")]
10 StaleGeneration { reference: u64, current: u64 },
11 #[error("span out of ring bounds")]
12 OutOfBounds,
13}
14
15#[derive(Debug, Clone, Copy)]
16pub struct RingAttachment {
17 pub ring_id: u32,
18 pub kind: u32,
19 pub role: u32,
20 pub slots: u32,
21 pub slot_bytes: u32,
22 pub base: *mut u8,
23 pub len: usize,
24}
25
26pub trait Rings {
27 fn read_tokens(&self, r: &TokenRef) -> Result<Vec<u32>, RingError>;
28
29 fn write_tokens(&mut self, tokens: &[u32]) -> Result<TokenRef, RingError>;
30
31 fn write_logits_row(&mut self, row: &[f32]) -> RingRef;
32
33 fn read_logits_row(&self, r: &RingRef) -> Result<Vec<f32>, RingError>;
34
35 fn yield_requested(&self) -> bool {
38 false
39 }
40
41 fn latency_wanted(&self) -> bool {
44 false
45 }
46}
47
48pub const TOKEN_RING_IN: u32 = 1;
49pub const TOKEN_RING_OUT: u32 = 2;
50pub const LOGITS_RING: u32 = 3;
51
52#[derive(Debug)]
53pub struct InMemoryRings {
54 token_in: RingBuf<Vec<u32>>,
55 token_out: RingBuf<Vec<u32>>,
56 logits: RingBuf<Vec<f32>>,
57 yield_requested: bool,
58 latency_wanted: bool,
59}
60
61#[derive(Debug)]
62struct RingBuf<T> {
63 slots: Vec<Option<(u64, T)>>,
64 next_index: usize,
65 next_generation: u64,
66}
67
68impl<T: Clone> RingBuf<T> {
69 fn new(slots: usize) -> Self {
70 RingBuf {
71 slots: vec![None; slots],
72 next_index: 0,
73 next_generation: 1,
74 }
75 }
76
77 fn push(&mut self, payload: T) -> (u32, u64) {
78 let index = self.next_index;
79 let generation = self.next_generation;
80 self.slots[index] = Some((generation, payload));
81 self.next_index = (index + 1) % self.slots.len();
82 self.next_generation += 1;
83 (index as u32, generation)
84 }
85
86 fn get(&self, index: u32, generation: u64) -> Result<&T, RingError> {
87 let slot = self
88 .slots
89 .get(index as usize)
90 .ok_or(RingError::OutOfBounds)?;
91 match slot {
92 Some((gen, payload)) if *gen == generation => Ok(payload),
93 Some((gen, _)) => Err(RingError::StaleGeneration {
94 reference: generation,
95 current: *gen,
96 }),
97 None => Err(RingError::StaleGeneration {
98 reference: generation,
99 current: 0,
100 }),
101 }
102 }
103}
104
105impl InMemoryRings {
106 pub fn new() -> Self {
107 InMemoryRings {
108 token_in: RingBuf::new(64),
109 token_out: RingBuf::new(64),
110 logits: RingBuf::new(16),
111 yield_requested: false,
112 latency_wanted: false,
113 }
114 }
115
116 pub fn set_yield(&mut self, on: bool) {
118 self.yield_requested = on;
119 }
120
121 pub fn set_latency(&mut self, on: bool) {
123 self.latency_wanted = on;
124 }
125
126 pub fn stage_prompt(&mut self, tokens: &[u32]) -> TokenRef {
127 let (index, generation) = self.token_in.push(tokens.to_vec());
128 TokenRef {
129 ring_id: TOKEN_RING_IN,
130 index,
131 count: tokens.len() as u32,
132 _pad0: 0,
133 generation,
134 }
135 }
136}
137
138impl Default for InMemoryRings {
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144impl Rings for InMemoryRings {
145 fn read_tokens(&self, r: &TokenRef) -> Result<Vec<u32>, RingError> {
146 let buf = match r.ring_id {
147 TOKEN_RING_IN => &self.token_in,
148 TOKEN_RING_OUT => &self.token_out,
149 other => return Err(RingError::UnknownRing(other)),
150 };
151 let tokens = buf.get(r.index, r.generation)?;
152 if tokens.len() != r.count as usize {
153 return Err(RingError::OutOfBounds);
154 }
155 Ok(tokens.clone())
156 }
157
158 fn write_tokens(&mut self, tokens: &[u32]) -> Result<TokenRef, RingError> {
159 let (index, generation) = self.token_out.push(tokens.to_vec());
160 Ok(TokenRef {
161 ring_id: TOKEN_RING_OUT,
162 index,
163 count: tokens.len() as u32,
164 _pad0: 0,
165 generation,
166 })
167 }
168
169 fn write_logits_row(&mut self, row: &[f32]) -> RingRef {
170 let (index, generation) = self.logits.push(row.to_vec());
171 RingRef {
172 ring_id: LOGITS_RING,
173 index,
174 generation,
175 }
176 }
177
178 fn read_logits_row(&self, r: &RingRef) -> Result<Vec<f32>, RingError> {
179 if r.ring_id != LOGITS_RING {
180 return Err(RingError::UnknownRing(r.ring_id));
181 }
182 self.logits.get(r.index, r.generation).cloned()
183 }
184
185 fn yield_requested(&self) -> bool {
186 self.yield_requested
187 }
188
189 fn latency_wanted(&self) -> bool {
190 self.latency_wanted
191 }
192}