Skip to main content

qubit_dcl/double_checked/
executor_lock_builder.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Builder state after a lock has been attached for
10//! [`super::DoubleCheckedLockExecutor`].
11//!
12//! # Author
13//!
14//! Haixing Hu
15
16use std::marker::PhantomData;
17
18use qubit_function::Tester;
19
20use super::{ExecutionLogger, executor_ready_builder::ExecutorReadyBuilder};
21use crate::lock::Lock;
22
23/// Builder state after a lock has been attached.
24///
25/// Call [`Self::when`] to configure the required condition tester.
26///
27/// # Type Parameters
28///
29/// * `L` - The lock type implementing [`Lock<T>`].
30/// * `T` - The data type protected by the lock.
31///
32/// # Author
33///
34/// Haixing Hu
35#[derive(Clone)]
36pub struct ExecutorLockBuilder<L, T> {
37    /// The lock to store in the executor.
38    pub(in crate::double_checked) lock: L,
39
40    /// Logger carried forward to the ready builder state.
41    pub(in crate::double_checked) logger: ExecutionLogger,
42
43    /// Whether panics from tester, callbacks, and task are captured as result errors.
44    pub(in crate::double_checked) catch_panics: bool,
45
46    /// Carries the protected data type.
47    pub(in crate::double_checked) _phantom: PhantomData<fn() -> T>,
48}
49
50impl<L, T> ExecutorLockBuilder<L, T>
51where
52    L: Lock<T>,
53{
54    /// Configures logging when the double-checked condition is not met.
55    #[inline]
56    pub fn log_unmet_condition(mut self, level: log::Level, message: impl Into<String>) -> Self {
57        self.logger.set_unmet_condition(Some(level), message);
58        self
59    }
60
61    /// Disables logging when the double-checked condition is not met.
62    #[inline]
63    pub fn disable_unmet_condition_logging(mut self) -> Self {
64        self.logger.disable_unmet_condition();
65        self
66    }
67
68    /// Configures logging when the prepare action fails.
69    #[inline]
70    pub fn log_prepare_failure(
71        mut self,
72        level: log::Level,
73        message_prefix: impl Into<String>,
74    ) -> Self {
75        self.logger.set_prepare_failure(Some(level), message_prefix);
76        self
77    }
78
79    /// Disables logging when the prepare action fails.
80    #[inline]
81    pub fn disable_prepare_failure_logging(mut self) -> Self {
82        self.logger.disable_prepare_failure();
83        self
84    }
85
86    /// Configures logging when the prepare commit action fails.
87    #[inline]
88    pub fn log_prepare_commit_failure(
89        mut self,
90        level: log::Level,
91        message_prefix: impl Into<String>,
92    ) -> Self {
93        self.logger
94            .set_prepare_commit_failure(Some(level), message_prefix);
95        self
96    }
97
98    /// Disables logging when the prepare commit action fails.
99    #[inline]
100    pub fn disable_prepare_commit_failure_logging(mut self) -> Self {
101        self.logger.disable_prepare_commit_failure();
102        self
103    }
104
105    /// Configures logging when the prepare rollback action fails.
106    #[inline]
107    pub fn log_prepare_rollback_failure(
108        mut self,
109        level: log::Level,
110        message_prefix: impl Into<String>,
111    ) -> Self {
112        self.logger
113            .set_prepare_rollback_failure(Some(level), message_prefix);
114        self
115    }
116
117    /// Disables logging when the prepare rollback action fails.
118    #[inline]
119    pub fn disable_prepare_rollback_failure_logging(mut self) -> Self {
120        self.logger.disable_prepare_rollback_failure();
121        self
122    }
123
124    /// Configures the required double-checked condition.
125    ///
126    /// The tester is executed outside and inside the lock. State read by the
127    /// outside check must be safe to access without this executor's lock.
128    ///
129    /// # Parameters
130    ///
131    /// * `tester` - The reusable condition tester.
132    ///
133    /// # Returns
134    ///
135    /// The builder state that can configure prepare callbacks and build the
136    /// executor.
137    #[inline]
138    pub fn when<Tst>(self, tester: Tst) -> ExecutorReadyBuilder<L, T>
139    where
140        Tst: Tester + Send + Sync + 'static,
141    {
142        ExecutorReadyBuilder {
143            lock: self.lock,
144            tester: tester.into_arc(),
145            logger: self.logger,
146            prepare_action: None,
147            rollback_prepare_action: None,
148            commit_prepare_action: None,
149            catch_panics: self.catch_panics,
150            _phantom: PhantomData,
151        }
152    }
153
154    /// Enables panic capture for tester, prepare callbacks, and task execution.
155    #[inline]
156    pub fn catch_panics(mut self) -> Self {
157        self.catch_panics = true;
158        self
159    }
160
161    /// Sets whether panic capture for tester, prepare callbacks, and task
162    /// execution is enabled.
163    #[inline]
164    pub fn set_catch_panics(mut self, catch_panics: bool) -> Self {
165        self.catch_panics = catch_panics;
166        self
167    }
168
169    /// Disables panic capture for tester, prepare callbacks, and task execution.
170    #[inline]
171    pub fn disable_catch_panics(mut self) -> Self {
172        self.catch_panics = false;
173        self
174    }
175}