Skip to main content

qubit_dcl/double_checked/
double_checked_lock_ready_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//! Convenience ready-builder state for [`super::DoubleCheckedLock`].
11
12use std::fmt::Display;
13
14use qubit_function::{
15    Callable,
16    CallableWith,
17    Runnable,
18    RunnableWith,
19};
20
21use super::{
22    DoubleCheckedLockExecutor,
23    ExecutionContext,
24    executor_ready_builder::ExecutorReadyBuilder,
25};
26use qubit_lock::Lock;
27
28/// Convenience builder state with tester attached.
29#[derive(Clone)]
30pub struct DoubleCheckedLockReadyBuilder<L, T> {
31    /// Reusable-executor builder delegated to by the convenience API.
32    pub(in crate::double_checked) inner: ExecutorReadyBuilder<L, T>,
33}
34
35impl<L, T> DoubleCheckedLockReadyBuilder<L, T>
36where
37    L: Lock<T>,
38{
39    /// Configures logging when the double-checked condition is not met.
40    ///
41    /// # Parameters
42    ///
43    /// * `level` - Log level used for unmet-condition messages.
44    /// * `message` - Full log message emitted when the condition is not met.
45    ///
46    /// # Returns
47    ///
48    /// This builder with unmet-condition logging configured.
49    #[inline]
50    #[must_use = "assign or chain the returned builder"]
51    pub fn log_unmet_condition(mut self, level: log::Level, message: impl Into<String>) -> Self {
52        self.inner = self.inner.log_unmet_condition(level, message);
53        self
54    }
55
56    /// Disables logging when the double-checked condition is not met.
57    ///
58    /// # Returns
59    ///
60    /// This builder with unmet-condition logging disabled.
61    #[inline]
62    #[must_use = "assign or chain the returned builder"]
63    pub fn disable_unmet_condition_logging(mut self) -> Self {
64        self.inner = self.inner.disable_unmet_condition_logging();
65        self
66    }
67
68    /// Configures logging when the prepare action fails.
69    ///
70    /// # Parameters
71    ///
72    /// * `level` - Log level used for prepare failure messages.
73    /// * `message_prefix` - Prefix placed before the prepare failure text.
74    ///
75    /// # Returns
76    ///
77    /// This builder with prepare failure logging configured.
78    #[inline]
79    #[must_use = "assign or chain the returned builder"]
80    pub fn log_prepare_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
81        self.inner = self.inner.log_prepare_failure(level, message_prefix);
82        self
83    }
84
85    /// Disables logging when the prepare action fails.
86    ///
87    /// # Returns
88    ///
89    /// This builder with prepare failure logging disabled.
90    #[inline]
91    #[must_use = "assign or chain the returned builder"]
92    pub fn disable_prepare_failure_logging(mut self) -> Self {
93        self.inner = self.inner.disable_prepare_failure_logging();
94        self
95    }
96
97    /// Configures logging when the prepare commit action fails.
98    ///
99    /// # Parameters
100    ///
101    /// * `level` - Log level used for prepare-commit failure messages.
102    /// * `message_prefix` - Prefix placed before the prepare-commit failure
103    ///   text.
104    ///
105    /// # Returns
106    ///
107    /// This builder with prepare-commit failure logging configured.
108    #[inline]
109    #[must_use = "assign or chain the returned builder"]
110    pub fn log_prepare_commit_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
111        self.inner = self.inner.log_prepare_commit_failure(level, message_prefix);
112        self
113    }
114
115    /// Disables logging when the prepare commit action fails.
116    ///
117    /// # Returns
118    ///
119    /// This builder with prepare-commit failure logging disabled.
120    #[inline]
121    #[must_use = "assign or chain the returned builder"]
122    pub fn disable_prepare_commit_failure_logging(mut self) -> Self {
123        self.inner = self.inner.disable_prepare_commit_failure_logging();
124        self
125    }
126
127    /// Configures logging when the prepare rollback action fails.
128    ///
129    /// # Parameters
130    ///
131    /// * `level` - Log level used for prepare-rollback failure messages.
132    /// * `message_prefix` - Prefix placed before the prepare-rollback failure
133    ///   text.
134    ///
135    /// # Returns
136    ///
137    /// This builder with prepare-rollback failure logging configured.
138    #[inline]
139    #[must_use = "assign or chain the returned builder"]
140    pub fn log_prepare_rollback_failure(mut self, level: log::Level, message_prefix: impl Into<String>) -> Self {
141        self.inner = self.inner.log_prepare_rollback_failure(level, message_prefix);
142        self
143    }
144
145    /// Disables logging when the prepare rollback action fails.
146    ///
147    /// # Returns
148    ///
149    /// This builder with prepare-rollback failure logging disabled.
150    #[inline]
151    #[must_use = "assign or chain the returned builder"]
152    pub fn disable_prepare_rollback_failure_logging(mut self) -> Self {
153        self.inner = self.inner.disable_prepare_rollback_failure_logging();
154        self
155    }
156
157    /// Enables panic capture for tester, prepare callbacks, and task execution.
158    ///
159    /// # Returns
160    ///
161    /// This builder with panic capture enabled.
162    #[inline]
163    #[must_use = "assign or chain the returned builder"]
164    pub fn catch_panics(mut self) -> Self {
165        self.inner = self.inner.catch_panics();
166        self
167    }
168
169    /// Derives a builder with panic capture enabled or disabled for tester,
170    /// prepare callbacks, and task execution.
171    ///
172    /// # Parameters
173    ///
174    /// * `catch_panics` - `true` to capture panics as execution errors, or
175    ///   `false` to let panics unwind.
176    ///
177    /// # Returns
178    ///
179    /// A reconfigured builder with the updated panic-capture setting.
180    #[inline]
181    #[must_use = "assign or chain the returned builder"]
182    pub fn with_panic_capture(mut self, catch_panics: bool) -> Self {
183        self.inner = self.inner.with_panic_capture(catch_panics);
184        self
185    }
186
187    /// Disables panic capture for tester, prepare callbacks, and task execution.
188    ///
189    /// # Returns
190    ///
191    /// This builder with panic capture disabled.
192    #[inline]
193    #[must_use = "assign or chain the returned builder"]
194    pub fn disable_catch_panics(mut self) -> Self {
195        self.inner = self.inner.disable_catch_panics();
196        self
197    }
198
199    /// Sets the prepare action.
200    ///
201    /// # Parameters
202    ///
203    /// * `prepare_action` - Fallible action to run after the first condition
204    ///   check and before locking.
205    ///
206    /// # Returns
207    ///
208    /// This builder with prepare configured.
209    ///
210    /// # Errors
211    ///
212    /// This builder method does not return errors. If `prepare_action` later
213    /// returns an error during execution, the execution result becomes
214    /// [`super::ExecutionResult::Failed`] with
215    /// [`super::ExecutorError::PrepareFailed`].
216    #[inline]
217    #[must_use = "assign or chain the returned builder"]
218    pub fn prepare<Rn, E>(mut self, prepare_action: Rn) -> Self
219    where
220        Rn: Runnable<E> + Send + 'static,
221        E: Display,
222    {
223        self.inner = self.inner.prepare(prepare_action);
224        self
225    }
226
227    /// Sets the rollback action for prepare.
228    ///
229    /// # Parameters
230    ///
231    /// * `rollback_prepare_action` - Fallible action to run when prepare
232    ///   completed but the second condition check or task fails.
233    ///
234    /// # Returns
235    ///
236    /// This builder with prepare rollback configured.
237    ///
238    /// # Errors
239    ///
240    /// This builder method does not return errors. If
241    /// `rollback_prepare_action` later returns an error during execution, the
242    /// execution result becomes [`super::ExecutionResult::Failed`] with
243    /// [`super::ExecutorError::PrepareRollbackFailed`].
244    #[inline]
245    #[must_use = "assign or chain the returned builder"]
246    pub fn rollback_prepare<Rn, E>(mut self, rollback_prepare_action: Rn) -> Self
247    where
248        Rn: Runnable<E> + Send + 'static,
249        E: Display,
250    {
251        self.inner = self.inner.rollback_prepare(rollback_prepare_action);
252        self
253    }
254
255    /// Sets the commit action for prepare.
256    ///
257    /// # Parameters
258    ///
259    /// * `commit_prepare_action` - Fallible action to run when prepare
260    ///   completed and the task succeeds.
261    ///
262    /// # Returns
263    ///
264    /// This builder with prepare commit configured.
265    ///
266    /// # Errors
267    ///
268    /// This builder method does not return errors. If `commit_prepare_action`
269    /// later returns an error during execution, the execution result becomes
270    /// [`super::ExecutionResult::Failed`] with
271    /// [`super::ExecutorError::PrepareCommitFailed`].
272    #[inline]
273    #[must_use = "assign or chain the returned builder"]
274    pub fn commit_prepare<Rn, E>(mut self, commit_prepare_action: Rn) -> Self
275    where
276        Rn: Runnable<E> + Send + 'static,
277        E: Display,
278    {
279        self.inner = self.inner.commit_prepare(commit_prepare_action);
280        self
281    }
282
283    /// Builds a reusable [`DoubleCheckedLockExecutor`].
284    ///
285    /// # Returns
286    ///
287    /// A reusable executor containing the configured lock, tester, logger, and
288    /// prepare lifecycle callbacks.
289    #[inline]
290    #[must_use = "use the returned executor"]
291    pub fn build(self) -> DoubleCheckedLockExecutor<L, T> {
292        self.inner.build()
293    }
294
295    /// Runs a callable task with one-shot executor creation.
296    ///
297    /// # Parameters
298    ///
299    /// * `task` - Zero-argument callable executed after both condition checks
300    ///   pass.
301    ///
302    /// # Returns
303    ///
304    /// An [`ExecutionContext`] containing success, unmet-condition, or failure
305    /// information.
306    #[inline]
307    pub fn call<C, R, E>(self, task: C) -> ExecutionContext<R, E>
308    where
309        C: Callable<R, E>,
310        E: Display,
311    {
312        self.inner.build().call(task)
313    }
314
315    /// Runs a runnable task with one-shot executor creation.
316    ///
317    /// # Parameters
318    ///
319    /// * `task` - Zero-argument runnable executed after both condition checks
320    ///   pass.
321    ///
322    /// # Returns
323    ///
324    /// An [`ExecutionContext`] containing success, unmet-condition, or failure
325    /// information.
326    #[inline]
327    pub fn execute<Rn, E>(self, task: Rn) -> ExecutionContext<(), E>
328    where
329        Rn: Runnable<E>,
330        E: Display,
331    {
332        self.inner.build().execute(task)
333    }
334
335    /// Runs a callable task with mutable protected data.
336    ///
337    /// # Parameters
338    ///
339    /// * `task` - Callable receiving `&mut T` after both condition checks pass.
340    ///
341    /// # Returns
342    ///
343    /// An [`ExecutionContext`] containing success, unmet-condition, or failure
344    /// information.
345    #[inline]
346    pub fn call_with<C, R, E>(self, task: C) -> ExecutionContext<R, E>
347    where
348        C: CallableWith<T, R, E>,
349        E: Display,
350    {
351        self.inner.build().call_with(task)
352    }
353
354    /// Runs a runnable task with mutable protected data.
355    ///
356    /// # Parameters
357    ///
358    /// * `task` - Runnable receiving `&mut T` after both condition checks pass.
359    ///
360    /// # Returns
361    ///
362    /// An [`ExecutionContext`] containing success, unmet-condition, or failure
363    /// information.
364    #[inline]
365    pub fn execute_with<Rn, E>(self, task: Rn) -> ExecutionContext<(), E>
366    where
367        Rn: RunnableWith<T, E>,
368        E: Display,
369    {
370        self.inner.build().execute_with(task)
371    }
372}