Skip to main content

qubit_dcl/double_checked/
executor_lock_builder.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//! Builder state after a lock has been attached for
11//! [`super::DoubleCheckedLockExecutor`].
12//!
13
14use std::marker::PhantomData;
15
16use qubit_function::Tester;
17
18use super::{
19    ExecutionLogger,
20    executor_ready_builder::ExecutorReadyBuilder,
21};
22use qubit_lock::Lock;
23
24/// Builder state after a lock has been attached.
25///
26/// Call [`Self::when`] to configure the required condition tester.
27///
28/// # Type Parameters
29///
30/// * `L` - The lock type implementing [`Lock<T>`].
31/// * `T` - The data type protected by the lock.
32///
33#[derive(Clone)]
34pub struct ExecutorLockBuilder<L, T> {
35    /// The lock to store in the executor.
36    pub(in crate::double_checked) lock: L,
37
38    /// Logger carried forward to the ready builder state.
39    pub(in crate::double_checked) logger: ExecutionLogger,
40
41    /// Whether panics from tester, callbacks, and task are captured as result errors.
42    pub(in crate::double_checked) catch_panics: bool,
43
44    /// Carries the protected data type.
45    pub(in crate::double_checked) _phantom: PhantomData<fn() -> T>,
46}
47
48impl<L, T> ExecutorLockBuilder<L, T>
49where
50    L: Lock<T>,
51{
52    /// Configures logging when the double-checked condition is not met.
53    ///
54    /// # Parameters
55    ///
56    /// * `level` - Log level used for unmet-condition messages.
57    /// * `message` - Full log message emitted when the condition is not met.
58    ///
59    /// # Returns
60    ///
61    /// This builder with unmet-condition logging configured.
62    #[inline]
63    #[must_use = "assign or chain the returned builder"]
64    pub fn log_unmet_condition(mut self, level: log::Level, message: impl Into<String>) -> Self {
65        self.logger.set_unmet_condition(Some(level), message);
66        self
67    }
68
69    /// Disables logging when the double-checked condition is not met.
70    ///
71    /// # Returns
72    ///
73    /// This builder with unmet-condition logging disabled.
74    #[inline]
75    #[must_use = "assign or chain the returned builder"]
76    pub fn disable_unmet_condition_logging(mut self) -> Self {
77        self.logger.disable_unmet_condition();
78        self
79    }
80
81    /// Configures logging when the prepare action fails.
82    ///
83    /// # Parameters
84    ///
85    /// * `level` - Log level used for prepare failure messages.
86    /// * `message_prefix` - Prefix placed before the prepare failure text.
87    ///
88    /// # Returns
89    ///
90    /// This builder with prepare failure logging configured.
91    #[inline]
92    #[must_use = "assign or chain the returned builder"]
93    pub fn log_prepare_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
94        self.logger.set_prepare_failure(Some(level), message_prefix);
95        self
96    }
97
98    /// Disables logging when the prepare action fails.
99    ///
100    /// # Returns
101    ///
102    /// This builder with prepare failure logging disabled.
103    #[inline]
104    #[must_use = "assign or chain the returned builder"]
105    pub fn disable_prepare_failure_logging(mut self) -> Self {
106        self.logger.disable_prepare_failure();
107        self
108    }
109
110    /// Configures logging when the prepare commit action fails.
111    ///
112    /// # Parameters
113    ///
114    /// * `level` - Log level used for prepare-commit failure messages.
115    /// * `message_prefix` - Prefix placed before the prepare-commit failure
116    ///   text.
117    ///
118    /// # Returns
119    ///
120    /// This builder with prepare-commit failure logging configured.
121    #[inline]
122    #[must_use = "assign or chain the returned builder"]
123    pub fn log_prepare_commit_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
124        self.logger.set_prepare_commit_failure(Some(level), message_prefix);
125        self
126    }
127
128    /// Disables logging when the prepare commit action fails.
129    ///
130    /// # Returns
131    ///
132    /// This builder with prepare-commit failure logging disabled.
133    #[inline]
134    #[must_use = "assign or chain the returned builder"]
135    pub fn disable_prepare_commit_failure_logging(mut self) -> Self {
136        self.logger.disable_prepare_commit_failure();
137        self
138    }
139
140    /// Configures logging when the prepare rollback action fails.
141    ///
142    /// # Parameters
143    ///
144    /// * `level` - Log level used for prepare-rollback failure messages.
145    /// * `message_prefix` - Prefix placed before the prepare-rollback failure
146    ///   text.
147    ///
148    /// # Returns
149    ///
150    /// This builder with prepare-rollback failure logging configured.
151    #[inline]
152    #[must_use = "assign or chain the returned builder"]
153    pub fn log_prepare_rollback_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
154        self.logger.set_prepare_rollback_failure(Some(level), message_prefix);
155        self
156    }
157
158    /// Disables logging when the prepare rollback action fails.
159    ///
160    /// # Returns
161    ///
162    /// This builder with prepare-rollback failure logging disabled.
163    #[inline]
164    #[must_use = "assign or chain the returned builder"]
165    pub fn disable_prepare_rollback_failure_logging(mut self) -> Self {
166        self.logger.disable_prepare_rollback_failure();
167        self
168    }
169
170    /// Configures the required double-checked condition.
171    ///
172    /// The tester is executed outside and inside the lock. State read by the
173    /// outside check must be safe to access without this executor's lock.
174    ///
175    /// # Parameters
176    ///
177    /// * `tester` - The reusable condition tester.
178    ///
179    /// # Returns
180    ///
181    /// The builder state that can configure prepare callbacks and build the
182    /// executor.
183    #[inline]
184    #[must_use = "assign or chain the returned builder"]
185    pub fn when<Tst>(self, tester: Tst) -> ExecutorReadyBuilder<L, T>
186    where
187        Tst: Tester + Send + Sync + 'static,
188    {
189        ExecutorReadyBuilder {
190            lock: self.lock,
191            tester: tester.into_arc(),
192            logger: self.logger,
193            prepare_action: None,
194            rollback_prepare_action: None,
195            commit_prepare_action: None,
196            catch_panics: self.catch_panics,
197            _phantom: PhantomData,
198        }
199    }
200
201    /// Enables panic capture for tester, prepare callbacks, and task execution.
202    ///
203    /// # Returns
204    ///
205    /// This builder with panic capture enabled.
206    #[inline]
207    #[must_use = "assign or chain the returned builder"]
208    pub fn catch_panics(mut self) -> Self {
209        self.catch_panics = true;
210        self
211    }
212
213    /// Derives a builder with panic capture enabled or disabled for tester,
214    /// prepare callbacks, and task execution.
215    ///
216    /// # Parameters
217    ///
218    /// * `catch_panics` - `true` to capture panics as execution errors, or
219    ///   `false` to let panics unwind.
220    ///
221    /// # Returns
222    ///
223    /// A reconfigured builder with the updated panic-capture setting.
224    #[inline]
225    #[must_use = "assign or chain the returned builder"]
226    pub fn with_panic_capture(mut self, catch_panics: bool) -> Self {
227        self.catch_panics = catch_panics;
228        self
229    }
230
231    /// Disables panic capture for tester, prepare callbacks, and task execution.
232    ///
233    /// # Returns
234    ///
235    /// This builder with panic capture disabled.
236    #[inline]
237    #[must_use = "assign or chain the returned builder"]
238    pub fn disable_catch_panics(mut self) -> Self {
239        self.catch_panics = false;
240        self
241    }
242}