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