Line data Source code
1 : //! A wrapper around `ArcSwap` that ensures there is only one writer at a time and writes
2 : //! don't block reads.
3 :
4 : use arc_swap::ArcSwap;
5 : use std::sync::Arc;
6 : use tokio::sync::TryLockError;
7 :
8 : pub struct GuardArcSwap<T> {
9 : inner: ArcSwap<T>,
10 : guard: tokio::sync::Mutex<()>,
11 : }
12 :
13 : pub struct Guard<'a, T> {
14 : _guard: tokio::sync::MutexGuard<'a, ()>,
15 : inner: &'a ArcSwap<T>,
16 : }
17 :
18 : impl<T> GuardArcSwap<T> {
19 892 : pub fn new(inner: T) -> Self {
20 892 : Self {
21 892 : inner: ArcSwap::new(Arc::new(inner)),
22 892 : guard: tokio::sync::Mutex::new(()),
23 892 : }
24 892 : }
25 :
26 0 : pub fn read(&self) -> Arc<T> {
27 0 : self.inner.load_full()
28 0 : }
29 :
30 0 : pub async fn write_guard(&self) -> Guard<'_, T> {
31 0 : Guard {
32 0 : _guard: self.guard.lock().await,
33 0 : inner: &self.inner,
34 0 : }
35 0 : }
36 :
37 1136 : pub fn try_write_guard(&self) -> Result<Guard<'_, T>, TryLockError> {
38 1136 : let guard = self.guard.try_lock()?;
39 1136 : Ok(Guard {
40 1136 : _guard: guard,
41 1136 : inner: &self.inner,
42 1136 : })
43 1136 : }
44 : }
45 :
46 : impl<T> Guard<'_, T> {
47 1136 : pub fn read(&self) -> Arc<T> {
48 1136 : self.inner.load_full()
49 1136 : }
50 :
51 640 : pub fn write(&mut self, value: T) {
52 640 : self.inner.store(Arc::new(value));
53 640 : }
54 : }
|