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