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 std::sync::Arc;
5 :
6 : use arc_swap::ArcSwap;
7 : use tokio::sync::TryLockError;
8 :
9 : pub struct GuardArcSwap<T> {
10 : inner: ArcSwap<T>,
11 : guard: tokio::sync::Mutex<()>,
12 : }
13 :
14 : pub struct Guard<'a, T> {
15 : _guard: tokio::sync::MutexGuard<'a, ()>,
16 : inner: &'a ArcSwap<T>,
17 : }
18 :
19 : impl<T> GuardArcSwap<T> {
20 904 : pub fn new(inner: T) -> Self {
21 904 : Self {
22 904 : inner: ArcSwap::new(Arc::new(inner)),
23 904 : guard: tokio::sync::Mutex::new(()),
24 904 : }
25 904 : }
26 :
27 728 : pub fn read(&self) -> Arc<T> {
28 728 : self.inner.load_full()
29 728 : }
30 :
31 0 : pub async fn write_guard(&self) -> Guard<'_, T> {
32 0 : Guard {
33 0 : _guard: self.guard.lock().await,
34 0 : inner: &self.inner,
35 0 : }
36 0 : }
37 :
38 1148 : pub fn try_write_guard(&self) -> Result<Guard<'_, T>, TryLockError> {
39 1148 : let guard = self.guard.try_lock()?;
40 1148 : Ok(Guard {
41 1148 : _guard: guard,
42 1148 : inner: &self.inner,
43 1148 : })
44 0 : }
45 : }
46 :
47 : impl<T> Guard<'_, T> {
48 1148 : pub fn read(&self) -> Arc<T> {
49 1148 : self.inner.load_full()
50 1148 : }
51 :
52 652 : pub fn write(&mut self, value: T) {
53 652 : self.inner.store(Arc::new(value));
54 652 : }
55 : }
|