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 crate::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(
94        mut self,
95        level: log::Level,
96        message_prefix: impl Into<String>,
97    ) -> Self {
98        self.logger.set_prepare_failure(Some(level), message_prefix);
99        self
100    }
101
102    /// Disables logging when the prepare action fails.
103    ///
104    /// # Returns
105    ///
106    /// This builder with prepare failure logging disabled.
107    #[inline]
108    #[must_use = "assign or chain the returned builder"]
109    pub fn disable_prepare_failure_logging(mut self) -> Self {
110        self.logger.disable_prepare_failure();
111        self
112    }
113
114    /// Configures logging when the prepare commit action fails.
115    ///
116    /// # Parameters
117    ///
118    /// * `level` - Log level used for prepare-commit failure messages.
119    /// * `message_prefix` - Prefix placed before the prepare-commit failure
120    ///   text.
121    ///
122    /// # Returns
123    ///
124    /// This builder with prepare-commit failure logging configured.
125    #[inline]
126    #[must_use = "assign or chain the returned builder"]
127    pub fn log_prepare_commit_failure(
128        mut self,
129        level: log::Level,
130        message_prefix: impl Into<String>,
131    ) -> Self {
132        self.logger
133            .set_prepare_commit_failure(Some(level), message_prefix);
134        self
135    }
136
137    /// Disables logging when the prepare commit action fails.
138    ///
139    /// # Returns
140    ///
141    /// This builder with prepare-commit failure logging disabled.
142    #[inline]
143    #[must_use = "assign or chain the returned builder"]
144    pub fn disable_prepare_commit_failure_logging(mut self) -> Self {
145        self.logger.disable_prepare_commit_failure();
146        self
147    }
148
149    /// Configures logging when the prepare rollback action fails.
150    ///
151    /// # Parameters
152    ///
153    /// * `level` - Log level used for prepare-rollback failure messages.
154    /// * `message_prefix` - Prefix placed before the prepare-rollback failure
155    ///   text.
156    ///
157    /// # Returns
158    ///
159    /// This builder with prepare-rollback failure logging configured.
160    #[inline]
161    #[must_use = "assign or chain the returned builder"]
162    pub fn log_prepare_rollback_failure(
163        mut self,
164        level: log::Level,
165        message_prefix: impl Into<String>,
166    ) -> Self {
167        self.logger
168            .set_prepare_rollback_failure(Some(level), message_prefix);
169        self
170    }
171
172    /// Disables logging when the prepare rollback action fails.
173    ///
174    /// # Returns
175    ///
176    /// This builder with prepare-rollback failure logging disabled.
177    #[inline]
178    #[must_use = "assign or chain the returned builder"]
179    pub fn disable_prepare_rollback_failure_logging(mut self) -> Self {
180        self.logger.disable_prepare_rollback_failure();
181        self
182    }
183
184    /// Configures the required double-checked condition.
185    ///
186    /// The tester is executed outside and inside the lock. State read by the
187    /// outside check must be safe to access without this executor's lock.
188    ///
189    /// # Parameters
190    ///
191    /// * `tester` - The reusable condition tester.
192    ///
193    /// # Returns
194    ///
195    /// The builder state that can configure prepare callbacks and build the
196    /// executor.
197    #[inline]
198    #[must_use = "assign or chain the returned builder"]
199    pub fn when<Tst>(self, tester: Tst) -> ExecutorReadyBuilder<L, T>
200    where
201        Tst: Tester + Send + Sync + 'static,
202    {
203        ExecutorReadyBuilder {
204            lock: self.lock,
205            tester: tester.into_arc(),
206            logger: self.logger,
207            prepare_action: None,
208            rollback_prepare_action: None,
209            commit_prepare_action: None,
210            catch_panics: self.catch_panics,
211            _phantom: PhantomData,
212        }
213    }
214
215    /// Enables panic capture for tester, prepare callbacks, and task execution.
216    ///
217    /// # Returns
218    ///
219    /// This builder with panic capture enabled.
220    #[inline]
221    #[must_use = "assign or chain the returned builder"]
222    pub fn catch_panics(mut self) -> Self {
223        self.catch_panics = true;
224        self
225    }
226
227    /// Derives a builder with panic capture enabled or disabled for tester,
228    /// prepare callbacks, and task execution.
229    ///
230    /// # Parameters
231    ///
232    /// * `catch_panics` - `true` to capture panics as execution errors, or
233    ///   `false` to let panics unwind.
234    ///
235    /// # Returns
236    ///
237    /// A reconfigured builder with the updated panic-capture setting.
238    #[inline]
239    #[must_use = "assign or chain the returned builder"]
240    pub fn with_panic_capture(mut self, catch_panics: bool) -> Self {
241        self.catch_panics = catch_panics;
242        self
243    }
244
245    /// Disables panic capture for tester, prepare callbacks, and task execution.
246    ///
247    /// # Returns
248    ///
249    /// This builder with panic capture disabled.
250    #[inline]
251    #[must_use = "assign or chain the returned builder"]
252    pub fn disable_catch_panics(mut self) -> Self {
253        self.catch_panics = false;
254        self
255    }
256}