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