1extern crate alloc;
2
3use alloc::collections::VecDeque;
4use alloc::vec::Vec;
5use parking_lot::RwLock;
6use std::sync::Arc;
7use tokio::sync::mpsc::error::{SendError, TryRecvError, TrySendError};
8use tokio::sync::Notify;
9
10pub trait FairGroup: Clone {
13 fn group_id(&self) -> Option<u32>;
14 fn get_size(&self) -> Option<usize>;
15}
16
17pub struct FairQueue<V: FairGroup> {
20 ctrl_group: VecDeque<Arc<V>>,
21 groups: Vec<VecDeque<Arc<V>>>,
22 pointer: usize,
23 max_group_size: usize,
24}
25
26impl<V: FairGroup> FairQueue<V> {
27 pub fn new(max_group_size: usize) -> Self {
28 Self {
29 ctrl_group: VecDeque::new(),
30 groups: Vec::new(),
31 pointer: 0,
32 max_group_size,
33 }
34 }
35
36 pub fn can_insert(&self, value: &V) -> bool {
38 match value.group_id() {
39 None => true, Some(group_id) => {
41 if let Some(group) = self
42 .groups
43 .iter()
44 .find(|group| group.front().map(|v| v.group_id()) == Some(Some(group_id)))
45 {
46 let can = group.len() < self.max_group_size;
47 if !can {
48 tracing::debug!(
53 group_id = %group_id,
54 len = group.len(),
55 max = self.max_group_size,
56 "fair channel group is full, sender waits"
57 );
58 }
59 can
60 } else {
61 true }
63 }
64 }
65 }
66
67 pub fn insert(&mut self, value: Arc<V>) -> bool {
70 match value.group_id() {
72 None => {
73 self.ctrl_group.push_back(value);
75 true
76 }
77 Some(group_id) => {
78 if let Some(group) = self
80 .groups
81 .iter_mut()
82 .find(|group| group.front().map(|v| v.group_id()) == Some(Some(group_id)))
83 {
84 if group.len() >= self.max_group_size {
85 return false; }
87 group.push_back(value);
88 } else {
89 let mut new_group = VecDeque::new();
90 new_group.push_back(value);
91 self.groups.push(new_group);
92 }
93 true
94 }
95 }
96 }
97
98 #[inline(always)]
99 pub fn pop(&mut self) -> Option<Arc<V>> {
100 if let Some(v) = self.ctrl_group.pop_front() {
101 return Some(v);
103 }
104 for _ in 0..self.groups.len() {
105 let pointer = self.pointer;
106 self.pointer = (pointer + 1) % self.groups.len();
108
109 let group = &mut self.groups[pointer];
110 let item = group.pop_front();
111
112 if item.is_some() {
113 if group.is_empty() {
114 self.groups.remove(pointer);
115 if pointer < self.groups.len() {
116 self.pointer = pointer;
117 } else {
118 self.pointer = 0;
119 }
120 }
121 return item;
122 }
123 }
124
125 None
126 }
127}
128
129struct ChannelState<T: FairGroup + 'static> {
131 queue: FairQueue<T>,
132 closed: bool,
133}
134
135impl<T: FairGroup + 'static> ChannelState<T> {
136 fn new(max_group_size: usize) -> Self {
137 Self {
138 queue: FairQueue::new(max_group_size),
139 closed: false,
140 }
141 }
142
143 fn can_insert(&self, value: &T) -> bool {
144 self.queue.can_insert(value)
145 }
146}
147
148pub struct FairSender<T: FairGroup + 'static> {
150 state: Arc<RwLock<ChannelState<T>>>,
151 notify_recv: Arc<Notify>,
152 notify_send: Arc<Notify>,
153}
154
155impl<T: FairGroup + 'static> Clone for FairSender<T> {
156 fn clone(&self) -> Self {
157 Self {
158 state: Arc::clone(&self.state),
159 notify_recv: Arc::clone(&self.notify_recv),
160 notify_send: Arc::clone(&self.notify_send),
161 }
162 }
163}
164
165impl<T: FairGroup + 'static> FairSender<T> {
166 pub async fn send(&self, value: T) -> Result<(), SendError<T>> {
168 let value_arc = Arc::new(value);
169
170 loop {
171 {
172 let mut state = self.state.write();
173 if state.closed {
174 return Err(SendError(
175 Arc::try_unwrap(value_arc).unwrap_or_else(|arc| (*arc).clone()),
176 ));
177 }
178
179 if state.can_insert(&value_arc) {
181 state.queue.insert(value_arc);
182 drop(state);
183 self.notify_recv.notify_waiters();
184 return Ok(());
185 }
186 }
187
188 self.notify_send.notified().await;
190 }
191 }
192
193 pub fn try_send(&self, value: T) -> Result<(), TrySendError<T>> {
195 let value_arc = Arc::new(value);
196
197 let mut state = self.state.write();
198 if state.closed {
199 return Err(TrySendError::Closed(
200 Arc::try_unwrap(value_arc).unwrap_or_else(|arc| (*arc).clone()),
201 ));
202 }
203
204 if !state.queue.can_insert(&value_arc) {
205 return Err(TrySendError::Full(
206 Arc::try_unwrap(value_arc).unwrap_or_else(|arc| (*arc).clone()),
207 ));
208 }
209
210 state.queue.insert(value_arc);
211 drop(state); self.notify_recv.notify_waiters();
213 Ok(())
214 }
215
216 pub async fn closed(&self) {
218 loop {
219 {
220 let state = self.state.read();
221 if state.closed {
222 return;
223 }
224 }
225
226 self.notify_send.notified().await;
228 }
229 }
230}
231
232pub struct FairReceiver<T: FairGroup + 'static> {
234 state: Arc<RwLock<ChannelState<T>>>,
235 notify_recv: Arc<Notify>,
236 notify_send: Arc<Notify>,
237}
238
239impl<T: FairGroup + 'static> FairReceiver<T> {
240 pub async fn recv(&mut self) -> Option<T> {
242 loop {
243 {
244 let mut state = self.state.write();
245 if let Some(value_arc) = state.queue.pop() {
246 drop(state);
247 self.notify_send.notify_waiters();
248 return Some(Arc::try_unwrap(value_arc).unwrap_or_else(|arc| (*arc).clone()));
249 }
250
251 if state.closed {
252 return None;
253 }
254 }
255
256 self.notify_recv.notified().await;
258 }
259 }
260
261 pub fn try_recv(&mut self) -> Result<T, TryRecvError> {
263 let mut state = self.state.write();
264
265 if let Some(value_arc) = state.queue.pop() {
266 drop(state); self.notify_send.notify_waiters();
268 return Ok(Arc::try_unwrap(value_arc).unwrap_or_else(|arc| (*arc).clone()));
269 }
270
271 if state.closed {
272 Err(TryRecvError::Disconnected)
273 } else {
274 Err(TryRecvError::Empty)
275 }
276 }
277
278 pub async fn close(&mut self) {
280 let mut state = self.state.write();
281 state.closed = true;
282 drop(state); self.notify_send.notify_waiters();
284 }
285}
286
287impl<T: FairGroup + 'static> Drop for FairReceiver<T> {
288 fn drop(&mut self) {
289 if let Some(mut state) = self.state.try_write() {
291 state.closed = true;
292 drop(state); self.notify_send.notify_waiters();
294 }
295 }
296}
297
298pub fn fair_channel<T: FairGroup + 'static>(
300 max_group_size: usize,
301) -> (FairSender<T>, FairReceiver<T>) {
302 let state = Arc::new(RwLock::new(ChannelState::new(max_group_size)));
303 let notify_recv = Arc::new(Notify::new());
304 let notify_send = Arc::new(Notify::new());
305
306 let sender = FairSender {
307 state: Arc::clone(&state),
308 notify_recv: Arc::clone(¬ify_recv),
309 notify_send: Arc::clone(¬ify_send),
310 };
311
312 let receiver = FairReceiver {
313 state,
314 notify_recv,
315 notify_send,
316 };
317
318 (sender, receiver)
319}
320
321#[cfg(test)]
322mod tests {
323 use super::*;
324 use std::sync::Mutex;
325 use tracing::subscriber::with_default;
326 use tracing_subscriber::layer::{Context, Layer};
327 use tracing_subscriber::prelude::*;
328 use tracing_subscriber::registry::LookupSpan;
329
330 #[derive(Debug, PartialEq, Clone)]
331 struct Event {
332 timestamp: u32,
333 user_id: &'static str,
334 }
335
336 impl FairGroup for Event {
337 fn group_id(&self) -> Option<u32> {
338 match self.user_id {
340 "user1" => Some(1),
341 "user2" => Some(2),
342 "user3" => Some(3),
343 _ => Some(0), }
345 }
346
347 fn get_size(&self) -> Option<usize> {
348 None }
350 }
351
352 #[test]
353 fn test_spaced_fairness() {
354 let event1 = Event {
355 timestamp: 1,
356 user_id: "user1",
357 };
358 let event2 = Event {
359 timestamp: 2,
360 user_id: "user2",
361 };
362 let event3 = Event {
363 timestamp: 3,
364 user_id: "user1",
365 };
366 let event4 = Event {
367 timestamp: 4,
368 user_id: "user3",
369 };
370 let event5 = Event {
371 timestamp: 5,
372 user_id: "user2",
373 };
374 let event6 = Event {
375 timestamp: 6,
376 user_id: "user1",
377 };
378 let event7 = Event {
379 timestamp: 7,
380 user_id: "user1",
381 };
382 let event8 = Event {
383 timestamp: 8,
384 user_id: "user3",
385 };
386
387 let mut queue = FairQueue::new(usize::MAX);
388
389 let event1_arc = Arc::new(event1.clone());
390 let event2_arc = Arc::new(event2.clone());
391 let event3_arc = Arc::new(event3.clone());
392 let event4_arc = Arc::new(event4.clone());
393 let event5_arc = Arc::new(event5.clone());
394 let event6_arc = Arc::new(event6.clone());
395 let event7_arc = Arc::new(event7.clone());
396 let event8_arc = Arc::new(event8.clone());
397
398 queue.insert(event1_arc.clone());
399 queue.insert(event2_arc.clone());
400 queue.insert(event3_arc.clone());
401 queue.insert(event4_arc.clone());
402 queue.insert(event5_arc.clone());
403 queue.insert(event6_arc.clone());
404 queue.insert(event7_arc.clone());
405 queue.insert(event8_arc.clone());
406
407 let mut results = Vec::new();
411 while let Some(event) = queue.pop() {
412 results.push(event);
413 }
414
415 assert_eq!(results.len(), 8);
417
418 let user1_events: Vec<_> = results.iter().filter(|e| e.user_id == "user1").collect();
421 let user2_events: Vec<_> = results.iter().filter(|e| e.user_id == "user2").collect();
422 let user3_events: Vec<_> = results.iter().filter(|e| e.user_id == "user3").collect();
423
424 assert_eq!(user1_events.len(), 4);
425 assert_eq!(user2_events.len(), 2);
426 assert_eq!(user3_events.len(), 2);
427 }
428
429 #[tokio::test]
430 async fn test_fair_channel_basic() {
431 let (tx, mut rx) = fair_channel(5);
432
433 let event1 = Event {
434 timestamp: 1,
435 user_id: "user1",
436 };
437 let event2 = Event {
438 timestamp: 2,
439 user_id: "user2",
440 };
441
442 tx.send(event1).await.unwrap();
443 tx.send(event2).await.unwrap();
444
445 let received1 = rx.recv().await.unwrap();
446 let received2 = rx.recv().await.unwrap();
447
448 assert_eq!(received1.timestamp, 1);
449 assert_eq!(received2.timestamp, 2);
450 }
451
452 #[tokio::test]
453 async fn test_fair_channel_fairness() {
454 let (tx, mut rx) = fair_channel(5);
455
456 for i in 0..6 {
458 let user_id = match i % 3 {
459 0 => "user1",
460 1 => "user2",
461 _ => "user3",
462 };
463 let event = Event {
464 timestamp: i,
465 user_id,
466 };
467 tx.send(event).await.unwrap();
468 }
469
470 let mut received = Vec::new();
472 for _ in 0..6 {
473 received.push(rx.recv().await.unwrap());
474 }
475
476 let user1_count = received.iter().filter(|e| e.user_id == "user1").count();
480 let user2_count = received.iter().filter(|e| e.user_id == "user2").count();
481 let user3_count = received.iter().filter(|e| e.user_id == "user3").count();
482
483 assert_eq!(user1_count, 2);
485 assert_eq!(user2_count, 2);
486 assert_eq!(user3_count, 2);
487
488 let mut timestamps: Vec<_> = received.iter().map(|e| e.timestamp).collect();
490 timestamps.sort();
491 assert_eq!(timestamps, vec![0, 1, 2, 3, 4, 5]);
492 }
493
494 #[tokio::test]
495 async fn test_fair_channel_closed_method() {
496 let (tx, mut rx) = fair_channel(5);
497
498 let tx_clone = tx.clone();
500 let closed_task = tokio::spawn(async move {
501 tx_clone.closed().await;
502 });
503
504 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
506
507 assert!(!closed_task.is_finished());
509
510 rx.close().await;
512
513 closed_task.await.unwrap();
515
516 let result = tx
518 .send(Event {
519 timestamp: 1,
520 user_id: "user1",
521 })
522 .await;
523 assert!(matches!(result, Err(SendError(_))));
524 }
525
526 #[derive(Clone, Default)]
536 struct LevelCapture(Arc<Mutex<Vec<(tracing::Level, String)>>>);
537
538 impl<S: tracing::Subscriber + for<'a> LookupSpan<'a>> Layer<S> for LevelCapture {
539 fn on_event(&self, event: &tracing::Event<'_>, _ctx: Context<'_, S>) {
540 let mut fields = String::new();
541 event.record(&mut FieldText(&mut fields));
542 self.0
543 .lock()
544 .unwrap()
545 .push((*event.metadata().level(), fields));
546 }
547 }
548
549 struct FieldText<'a>(&'a mut String);
550
551 impl tracing::field::Visit for FieldText<'_> {
552 fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn core::fmt::Debug) {
553 use core::fmt::Write as _;
554 let _ = write!(self.0, " {}={:?}", field.name(), value);
555 }
556 }
557
558 #[test]
559 fn full_group_is_reported_at_debug_with_group_id() {
560 let capture = LevelCapture::default();
561 let subscriber = tracing_subscriber::registry().with(capture.clone());
562
563 with_default(subscriber, || {
564 let mut queue: FairQueue<Event> = FairQueue::new(2);
566 let full = Event {
567 timestamp: 1,
568 user_id: "user1",
569 };
570 assert!(queue.insert(Arc::new(full.clone())));
571 assert!(queue.insert(Arc::new(Event {
572 timestamp: 2,
573 user_id: "user1",
574 })));
575 assert!(!queue.can_insert(&full));
577 });
578
579 let events = capture.0.lock().unwrap();
580 assert!(
581 !events
582 .iter()
583 .any(|(level, _)| *level == tracing::Level::ERROR),
584 "a full group is backpressure, not an error: {events:?}"
585 );
586 let debug_events: Vec<_> = events
587 .iter()
588 .filter(|(level, _)| *level == tracing::Level::DEBUG)
589 .collect();
590 assert_eq!(
591 debug_events.len(),
592 1,
593 "expected exactly one DEBUG event: {events:?}"
594 );
595 assert!(
596 debug_events[0].1.contains("group_id=1"),
597 "the event must name the group that is full: {:?}",
598 debug_events[0]
599 );
600 }
601}