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