1use std::sync::{
2 Arc, LazyLock,
3 atomic::{AtomicBool, AtomicU8, Ordering},
4};
5
6use arc_swap::ArcSwap;
7use tokio::sync::Notify;
8
9pub static KODIK_STATE: LazyLock<KodikState> = LazyLock::new(KodikState::default);
10
11#[derive(Debug, Default)]
12pub struct KodikState {
13 endpoint: ArcSwap<String>,
14 shift: AtomicU8,
15 notify: Notify,
16 updating: AtomicBool,
17}
18
19impl KodikState {
20 pub fn shift(&self) -> u8 {
21 self.shift.load(Ordering::Relaxed)
22 }
23
24 pub fn set_shift(&self, shift: u8) {
25 self.shift.store(shift, Ordering::Relaxed);
26 }
27
28 pub fn endpoint(&self) -> Arc<String> {
29 self.endpoint.load_full()
30 }
31
32 pub fn set_endpoint(&self, endpoint: String) {
33 self.endpoint.store(Arc::new(endpoint));
34 }
35
36 pub(crate) fn clear_endpoint(&self) {
37 self.set_endpoint(String::new());
38 }
39
40 pub(crate) fn try_begin_update(&self) -> bool {
41 !self.updating.swap(true, Ordering::AcqRel)
42 }
43
44 pub(crate) fn finish_update(&self, endpoint: String) {
45 self.set_endpoint(endpoint);
46 self.updating.store(false, Ordering::Release);
47 self.notify.notify_waiters();
48 }
49
50 pub(crate) async fn wait_for_update(&self) {
51 self.notify.notified().await;
52 }
53}