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