watchexec/crates/filterer/tagged/src/swaplock.rs

59 lines
1.4 KiB
Rust
Raw Normal View History

2021-10-16 06:13:32 +02:00
//! A value that is always available, but can be swapped out.
2021-09-28 11:21:51 +02:00
use std::fmt;
use tokio::sync::watch::{channel, error::SendError, Receiver, Ref, Sender};
2021-10-16 12:14:57 +02:00
/// A value that is always available, but can be swapped out.
///
/// This is a wrapper around a [Tokio `watch`][tokio::sync::watch]. The value can be read without
/// await, but can only be written to with async. Borrows should be held for as little as possible,
/// as they keep a read lock.
2021-09-28 11:21:51 +02:00
pub struct SwapLock<T: Clone> {
r: Receiver<T>,
s: Sender<T>,
}
impl<T> SwapLock<T>
where
T: Clone,
{
2021-10-16 12:14:57 +02:00
/// Create a new `SwapLock` with the given value.
2021-09-28 11:21:51 +02:00
pub fn new(inner: T) -> Self {
let (s, r) = channel(inner);
Self { r, s }
}
2021-10-16 12:14:57 +02:00
/// Get a reference to the value.
2021-09-28 11:21:51 +02:00
pub fn borrow(&self) -> Ref<'_, T> {
self.r.borrow()
}
2021-10-16 12:14:57 +02:00
/// Rewrite the value using a closure.
///
/// This obtains a clone of the value, and then calls the closure with a mutable reference to
/// it. Once the closure returns, the value is swapped in.
2023-01-06 14:53:49 +01:00
pub fn change(&self, f: impl FnOnce(&mut T)) -> Result<(), SendError<T>> {
2022-01-16 02:48:29 +01:00
let mut new = { self.r.borrow().clone() };
2021-09-28 11:21:51 +02:00
f(&mut new);
self.s.send(new)
}
2021-10-16 12:14:57 +02:00
/// Replace the value with a new one.
2023-01-06 14:53:49 +01:00
pub fn replace(&self, new: T) -> Result<(), SendError<T>> {
2021-09-28 11:21:51 +02:00
self.s.send(new)
}
}
impl<T> fmt::Debug for SwapLock<T>
where
T: fmt::Debug + Clone,
{
2022-04-13 12:59:43 +02:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
2021-09-28 11:21:51 +02:00
f.debug_struct("SwapLock")
.field("(watch)", &self.r)
.finish()
}
}