use std::fmt;
use std::sync::Arc;
use super::cas_attempt_failure_kind::CasAttemptFailureKind;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CasAttemptFailure<T, E> {
Conflict {
current: Arc<T>,
},
Retry {
current: Arc<T>,
error: E,
},
Abort {
current: Arc<T>,
error: E,
},
Timeout {
current: Arc<T>,
},
}
impl<T, E> CasAttemptFailure<T, E> {
#[inline]
pub(crate) fn conflict(current: Arc<T>) -> Self {
Self::Conflict { current }
}
#[inline]
pub(crate) fn retry(current: Arc<T>, error: E) -> Self {
Self::Retry { current, error }
}
#[inline]
pub(crate) fn abort(current: Arc<T>, error: E) -> Self {
Self::Abort { current, error }
}
#[inline]
#[cfg(feature = "tokio")]
pub(crate) fn timeout(current: Arc<T>) -> Self {
Self::Timeout { current }
}
#[inline]
pub fn current(&self) -> &Arc<T> {
match self {
Self::Conflict { current }
| Self::Retry { current, .. }
| Self::Abort { current, .. }
| Self::Timeout { current } => current,
}
}
#[inline]
pub fn kind(&self) -> CasAttemptFailureKind {
match self {
Self::Conflict { .. } => CasAttemptFailureKind::Conflict,
Self::Retry { .. } => CasAttemptFailureKind::Retry,
Self::Abort { .. } => CasAttemptFailureKind::Abort,
Self::Timeout { .. } => CasAttemptFailureKind::Timeout,
}
}
#[inline]
pub fn error(&self) -> Option<&E> {
match self {
Self::Retry { error, .. } | Self::Abort { error, .. } => Some(error),
Self::Conflict { .. } | Self::Timeout { .. } => None,
}
}
#[inline]
pub fn is_conflict(&self) -> bool {
matches!(self, Self::Conflict { .. })
}
#[inline]
pub fn is_retry(&self) -> bool {
matches!(self, Self::Retry { .. })
}
#[inline]
pub fn is_abort(&self) -> bool {
matches!(self, Self::Abort { .. })
}
#[inline]
pub fn is_timeout(&self) -> bool {
matches!(self, Self::Timeout { .. })
}
}
impl<T, E> fmt::Display for CasAttemptFailure<T, E>
where
E: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Conflict { .. } => write!(f, "compare-and-swap conflict"),
Self::Retry { error, .. } => write!(f, "retryable CAS failure: {error}"),
Self::Abort { error, .. } => write!(f, "aborted CAS failure: {error}"),
Self::Timeout { .. } => write!(f, "CAS attempt timed out"),
}
}
}