use arc_swap::{ArcSwap, Guard};
use std::fmt::Debug;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
#[derive(Clone)]
pub struct ConfigHandle<T: Clone + Send> {
inner: Arc<Inner<T>>,
}
struct Inner<T: Clone + Send> {
value: ArcSwap<T>,
generation: AtomicUsize,
}
impl<T: Clone + Send + Debug> Debug for ConfigHandle<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fmt.debug_struct("ConfigHandle")
.field("value", &self.inner.value)
.field("generation", &self.inner.generation)
.finish()
}
}
impl<T: Clone + Send> ConfigHandle<T> {
pub fn new(value: T) -> Self {
Self {
inner: Arc::new(Inner {
value: ArcSwap::from_pointee(value),
generation: AtomicUsize::new(0),
}),
}
}
pub fn generation(&self) -> usize {
self.inner.generation.load(Ordering::SeqCst)
}
pub fn update(&self, new_value: T) -> usize {
self.inner.value.swap(Arc::new(new_value));
let generation = self.inner.generation.fetch_add(1, Ordering::SeqCst) + 1;
generation
}
pub fn borrow(&self) -> Guard<Arc<T>> {
self.inner.value.load()
}
}