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}