//! A wrapper around `ArcSwap` that ensures there is only one writer at a time and writes //! don't block reads. use std::sync::Arc; use arc_swap::ArcSwap; use tokio::sync::TryLockError; pub struct GuardArcSwap { inner: ArcSwap, guard: tokio::sync::Mutex<()>, } pub struct Guard<'a, T> { _guard: tokio::sync::MutexGuard<'a, ()>, inner: &'a ArcSwap, } impl GuardArcSwap { pub fn new(inner: T) -> Self { Self { inner: ArcSwap::new(Arc::new(inner)), guard: tokio::sync::Mutex::new(()), } } pub fn read(&self) -> Arc { self.inner.load_full() } pub async fn write_guard(&self) -> Guard<'_, T> { Guard { _guard: self.guard.lock().await, inner: &self.inner, } } pub fn try_write_guard(&self) -> Result, TryLockError> { let guard = self.guard.try_lock()?; Ok(Guard { _guard: guard, inner: &self.inner, }) } } impl Guard<'_, T> { pub fn read(&self) -> Arc { self.inner.load_full() } pub fn write(&mut self, value: T) { self.inner.store(Arc::new(value)); } }