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 896 : pub fn new(inner: T) -> Self {
20 896 : Self {
21 896 : inner: ArcSwap::new(Arc::new(inner)),
22 896 : guard: tokio::sync::Mutex::new(()),
23 896 : }
24 896 : }
25 :
26 728 : pub fn read(&self) -> Arc<T> {
27 728 : self.inner.load_full()
28 728 : }
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 1140 : pub fn try_write_guard(&self) -> Result<Guard<'_, T>, TryLockError> {
38 1140 : let guard = self.guard.try_lock()?;
39 1140 : Ok(Guard {
40 1140 : _guard: guard,
41 1140 : inner: &self.inner,
42 1140 : })
43 1140 : }
44 : }
45 :
46 : impl<T> Guard<'_, T> {
47 1140 : pub fn read(&self) -> Arc<T> {
48 1140 : self.inner.load_full()
49 1140 : }
50 :
51 644 : pub fn write(&mut self, value: T) {
52 644 : self.inner.store(Arc::new(value));
53 644 : }
54 : }
|