1use std::sync::atomic::{AtomicU8, AtomicU64, Ordering, fence};
8
9use super::VoiceId;
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub enum VoiceState {
14 Playing,
15 Paused,
17 Stopping,
19 Finished,
20 Virtual,
22}
23
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
27pub struct VoiceStatus {
28 pub state: VoiceState,
29 pub position: u64,
30}
31
32const EMPTY: u64 = u64::MAX;
33
34struct Slot {
35 sequence: AtomicU64,
36 id: AtomicU64,
37 state: AtomicU8,
38 position: AtomicU64,
39}
40
41pub(super) struct Table {
42 slots: Box<[Slot]>,
43}
44
45impl Table {
46 pub fn new(slots: usize) -> Self {
47 Self {
48 slots: (0..slots)
49 .map(|_| Slot {
50 sequence: AtomicU64::new(0),
51 id: AtomicU64::new(EMPTY),
52 state: AtomicU8::new(0),
53 position: AtomicU64::new(0),
54 })
55 .collect(),
56 }
57 }
58 pub fn publish(&self, slot: usize, id: VoiceId, status: VoiceStatus) {
60 let s = &self.slots[slot];
61 let sequence = s.sequence.load(Ordering::Relaxed);
62 s.sequence
63 .store(sequence.wrapping_add(1), Ordering::Relaxed);
64 fence(Ordering::Release);
65 s.id.store(id.0, Ordering::Relaxed);
66 s.state.store(status.state as u8, Ordering::Relaxed);
67 s.position.store(status.position, Ordering::Relaxed);
68 s.sequence
69 .store(sequence.wrapping_add(2), Ordering::Release);
70 }
71 pub fn read(&self, id: VoiceId) -> Option<VoiceStatus> {
73 for s in self.slots.iter() {
74 loop {
75 let before = s.sequence.load(Ordering::Acquire);
76 if before % 2 == 1 {
77 std::hint::spin_loop();
78 continue;
79 }
80 let slot_id = s.id.load(Ordering::Relaxed);
81 let state = s.state.load(Ordering::Relaxed);
82 let position = s.position.load(Ordering::Relaxed);
83 fence(Ordering::Acquire);
84 if s.sequence.load(Ordering::Relaxed) != before {
85 continue;
86 }
87 if slot_id == id.0 {
88 let state = match state {
89 0 => VoiceState::Playing,
90 1 => VoiceState::Paused,
91 2 => VoiceState::Stopping,
92 4 => VoiceState::Virtual,
93 _ => VoiceState::Finished,
94 };
95 return Some(VoiceStatus { state, position });
96 }
97 break;
98 }
99 }
100 None
101 }
102}