Skip to main content

qubit_cas/fast/
fast_cas_error.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Terminal fast compare-and-swap failures.
11
12/// Terminal [`crate::FastCas`] failure.
13#[derive(Debug, Clone, Copy, Eq, PartialEq)]
14pub enum FastCasError<E> {
15    /// The operation aborted from a user decision.
16    Abort {
17        /// State observed by the aborting attempt.
18        current: usize,
19
20        /// Business error returned by the operation.
21        error: E,
22
23        /// Number of attempts consumed before aborting.
24        attempts: u32,
25    },
26
27    /// CAS conflicts exhausted the retry policy.
28    Conflict {
29        /// Most recent state observed after the final failed CAS.
30        current: usize,
31
32        /// Number of attempts consumed before giving up.
33        attempts: u32,
34    },
35}
36
37impl<E> FastCasError<E> {
38    /// Returns the current state captured by the terminal failure.
39    ///
40    /// # Returns
41    /// The observed state code at failure.
42    #[inline]
43    pub const fn current(&self) -> usize {
44        match self {
45            Self::Abort { current, .. } | Self::Conflict { current, .. } => *current,
46        }
47    }
48
49    /// Returns the number of attempts consumed before failure.
50    ///
51    /// # Returns
52    /// Number of attempts executed by the operation.
53    #[inline]
54    pub const fn attempts(&self) -> u32 {
55        match self {
56            Self::Abort { attempts, .. } | Self::Conflict { attempts, .. } => *attempts,
57        }
58    }
59
60    /// Tests whether this failure came from an abort decision.
61    ///
62    /// # Returns
63    /// `true` for [`FastCasError::Abort`].
64    #[inline]
65    pub const fn is_abort(&self) -> bool {
66        matches!(self, Self::Abort { .. })
67    }
68
69    /// Tests whether this failure came from exhausted CAS conflicts.
70    ///
71    /// # Returns
72    /// `true` for [`FastCasError::Conflict`].
73    #[inline]
74    pub const fn is_conflict(&self) -> bool {
75        matches!(self, Self::Conflict { .. })
76    }
77
78    /// Returns the business error for abort failures.
79    ///
80    /// # Returns
81    /// `Some(error)` for abort failures, or `None` for conflict failures.
82    #[inline]
83    pub const fn error(&self) -> Option<&E> {
84        match self {
85            Self::Abort { error, .. } => Some(error),
86            Self::Conflict { .. } => None,
87        }
88    }
89
90    /// Consumes this failure and returns the business error when present.
91    ///
92    /// # Returns
93    /// `Some(error)` for abort failures, or `None` for conflict failures.
94    #[inline]
95    pub fn into_error(self) -> Option<E> {
96        match self {
97            Self::Abort { error, .. } => Some(error),
98            Self::Conflict { .. } => None,
99        }
100    }
101}