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::{ExecutionLogger, executor_ready_builder::ExecutorReadyBuilder};
19use crate::lock::Lock;
20
21/// Builder state after a lock has been attached.
22///
23/// Call [`Self::when`] to configure the required condition tester.
24///
25/// # Type Parameters
26///
27/// * `L` - The lock type implementing [`Lock<T>`].
28/// * `T` - The data type protected by the lock.
29///
30#[derive(Clone)]
31pub struct ExecutorLockBuilder<L, T> {
32    /// The lock to store in the executor.
33    pub(in crate::double_checked) lock: L,
34
35    /// Logger carried forward to the ready builder state.
36    pub(in crate::double_checked) logger: ExecutionLogger,
37
38    /// Whether panics from tester, callbacks, and task are captured as result errors.
39    pub(in crate::double_checked) catch_panics: bool,
40
41    /// Carries the protected data type.
42    pub(in crate::double_checked) _phantom: PhantomData<fn() -> T>,
43}
44
45impl<L, T> ExecutorLockBuilder<L, T>
46where
47    L: Lock<T>,
48{
49    /// Configures logging when the double-checked condition is not met.
50    #[inline]
51    pub fn log_unmet_condition(mut self, level: log::Level, message: impl Into<String>) -> Self {
52        self.logger.set_unmet_condition(Some(level), message);
53        self
54    }
55
56    /// Disables logging when the double-checked condition is not met.
57    #[inline]
58    pub fn disable_unmet_condition_logging(mut self) -> Self {
59        self.logger.disable_unmet_condition();
60        self
61    }
62
63    /// Configures logging when the prepare action fails.
64    #[inline]
65    pub fn log_prepare_failure(
66        mut self,
67        level: log::Level,
68        message_prefix: impl Into<String>,
69    ) -> Self {
70        self.logger.set_prepare_failure(Some(level), message_prefix);
71        self
72    }
73
74    /// Disables logging when the prepare action fails.
75    #[inline]
76    pub fn disable_prepare_failure_logging(mut self) -> Self {
77        self.logger.disable_prepare_failure();
78        self
79    }
80
81    /// Configures logging when the prepare commit action fails.
82    #[inline]
83    pub fn log_prepare_commit_failure(
84        mut self,
85        level: log::Level,
86        message_prefix: impl Into<String>,
87    ) -> Self {
88        self.logger
89            .set_prepare_commit_failure(Some(level), message_prefix);
90        self
91    }
92
93    /// Disables logging when the prepare commit action fails.
94    #[inline]
95    pub fn disable_prepare_commit_failure_logging(mut self) -> Self {
96        self.logger.disable_prepare_commit_failure();
97        self
98    }
99
100    /// Configures logging when the prepare rollback action fails.
101    #[inline]
102    pub fn log_prepare_rollback_failure(
103        mut self,
104        level: log::Level,
105        message_prefix: impl Into<String>,
106    ) -> Self {
107        self.logger
108            .set_prepare_rollback_failure(Some(level), message_prefix);
109        self
110    }
111
112    /// Disables logging when the prepare rollback action fails.
113    #[inline]
114    pub fn disable_prepare_rollback_failure_logging(mut self) -> Self {
115        self.logger.disable_prepare_rollback_failure();
116        self
117    }
118
119    /// Configures the required double-checked condition.
120    ///
121    /// The tester is executed outside and inside the lock. State read by the
122    /// outside check must be safe to access without this executor's lock.
123    ///
124    /// # Parameters
125    ///
126    /// * `tester` - The reusable condition tester.
127    ///
128    /// # Returns
129    ///
130    /// The builder state that can configure prepare callbacks and build the
131    /// executor.
132    #[inline]
133    pub fn when<Tst>(self, tester: Tst) -> ExecutorReadyBuilder<L, T>
134    where
135        Tst: Tester + Send + Sync + 'static,
136    {
137        ExecutorReadyBuilder {
138            lock: self.lock,
139            tester: tester.into_arc(),
140            logger: self.logger,
141            prepare_action: None,
142            rollback_prepare_action: None,
143            commit_prepare_action: None,
144            catch_panics: self.catch_panics,
145            _phantom: PhantomData,
146        }
147    }
148
149    /// Enables panic capture for tester, prepare callbacks, and task execution.
150    #[inline]
151    pub fn catch_panics(mut self) -> Self {
152        self.catch_panics = true;
153        self
154    }
155
156    /// Sets whether panic capture for tester, prepare callbacks, and task
157    /// execution is enabled.
158    #[inline]
159    pub fn set_catch_panics(mut self, catch_panics: bool) -> Self {
160        self.catch_panics = catch_panics;
161        self
162    }
163
164    /// Disables panic capture for tester, prepare callbacks, and task execution.
165    #[inline]
166    pub fn disable_catch_panics(mut self) -> Self {
167        self.catch_panics = false;
168        self
169    }
170}