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