mod watch_error;
use openraft_macros::add_async_trait;
use openraft_macros::since;
pub use watch_error::RecvError;
pub use watch_error::SendError;
use crate::OptionalSend;
use crate::OptionalSync;
pub trait Watch: Sized + OptionalSend {
type Sender<T: OptionalSend + OptionalSync>: WatchSender<Self, T>;
type Receiver<T: OptionalSend + OptionalSync>: WatchReceiver<Self, T>;
type Ref<'a, T: OptionalSend + 'a>: std::ops::Deref<Target = T> + 'a;
#[track_caller]
fn channel<T: OptionalSend + OptionalSync>(init: T) -> (Self::Sender<T>, Self::Receiver<T>);
}
pub trait WatchSender<W, T>: OptionalSend + Clone
where
W: Watch,
T: OptionalSend + OptionalSync,
{
#[track_caller]
fn send(&self, value: T) -> Result<(), SendError<T>>;
#[track_caller]
fn send_if_modified<F>(&self, modify: F) -> bool
where F: FnOnce(&mut T) -> bool;
#[track_caller]
fn borrow_watched(&self) -> W::Ref<'_, T>;
#[track_caller]
fn subscribe(&self) -> W::Receiver<T>;
fn send_if_different(&self, value: T) -> bool
where T: PartialEq {
self.send_if_modified(|current| {
if *current != value {
*current = value;
true
} else {
false
}
})
}
fn send_if_greater(&self, value: T) -> bool
where T: PartialOrd {
self.send_if_modified(|current| {
if value > *current {
*current = value;
true
} else {
false
}
})
}
}
#[add_async_trait]
pub trait WatchReceiver<W, T>: OptionalSend + OptionalSync + Clone
where
W: Watch,
T: OptionalSend + OptionalSync,
{
async fn changed(&mut self) -> Result<(), RecvError>;
#[track_caller]
fn borrow_watched(&self) -> W::Ref<'_, T>;
#[since(version = "0.10.0")]
#[track_caller]
fn borrow_and_update(&mut self) -> W::Ref<'_, T>;
async fn wait_until_ge(&mut self, value: &T) -> Result<T, RecvError>
where T: PartialOrd + Clone {
loop {
{
let current = self.borrow_watched();
if &*current >= value {
return Ok(current.clone());
}
}
self.changed().await?;
}
}
async fn wait_until<F>(&mut self, condition: F) -> Result<T, RecvError>
where
T: Clone,
F: Fn(&T) -> bool + OptionalSend,
{
loop {
{
let current = self.borrow_watched();
if condition(&*current) {
return Ok(current.clone());
}
}
self.changed().await?;
}
}
}