use std::sync::Arc;
use crate::err::Error;
use super::{Shared, State};
#[repr(transparent)]
pub struct SetCtx<T, S: Clone, E>(pub(crate) Arc<Shared<T, S, E>>);
impl<T, S, E> SetCtx<T, S, E>
where
S: Clone
{
pub fn set_state(&self, s: S) -> Result<(), Error<S, E>> {
let mut inner = self.0.inner.lock();
if inner.wctx_dropped {
return Err(Error::LostWaiter);
}
inner.sctx_state = s;
drop(inner);
Ok(())
}
pub fn set(self, data: T) -> Result<(), Error<S, E>> {
let mut inner = self.0.inner.lock();
if inner.wctx_dropped {
return Err(Error::LostWaiter);
}
inner.state = State::Data(data);
self.0.notify_waiter(&mut inner);
drop(inner);
Ok(())
}
pub fn fail(self, error: E) -> Result<(), Error<S, E>> {
let mut inner = self.0.inner.lock();
if inner.wctx_dropped {
return Err(Error::LostWaiter);
}
inner.state = State::Err(Error::App(error));
self.0.notify_waiter(&mut inner);
drop(inner);
Ok(())
}
}
impl<T, S, E> Drop for SetCtx<T, S, E>
where
S: Clone
{
fn drop(&mut self) {
let mut inner = self.0.inner.lock();
match inner.state {
State::Waiting => {
inner.state = State::Err(Error::Aborted(inner.sctx_state.clone()));
self.0.notify_waiter(&mut inner);
drop(inner);
}
State::Data(_) | State::Err(_) | State::Finalized => {
}
}
}
}