qubit_dcl/double_checked/executor_lock_builder.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! Builder state after a lock has been attached for
10//! [`super::DoubleCheckedLockExecutor`].
11//!
12//! # Author
13//!
14//! Haixing Hu
15
16use std::marker::PhantomData;
17
18use qubit_function::Tester;
19
20use super::{
21 ExecutionLogger,
22 executor_ready_builder::ExecutorReadyBuilder,
23};
24use crate::lock::Lock;
25
26/// Builder state after a lock has been attached.
27///
28/// Call [`Self::when`] to configure the required condition tester.
29///
30/// # Type Parameters
31///
32/// * `L` - The lock type implementing [`Lock<T>`].
33/// * `T` - The data type protected by the lock.
34///
35/// # Author
36///
37/// Haixing Hu
38#[derive(Clone)]
39pub struct ExecutorLockBuilder<L, T> {
40 /// The lock to store in the executor.
41 pub(in crate::double_checked) lock: L,
42
43 /// Logger carried forward to the ready builder state.
44 pub(in crate::double_checked) logger: ExecutionLogger,
45
46 /// Carries the protected data type.
47 pub(in crate::double_checked) _phantom: PhantomData<fn() -> T>,
48}
49
50impl<L, T> ExecutorLockBuilder<L, T>
51where
52 L: Lock<T>,
53{
54 /// Configures logging when the double-checked condition is not met.
55 #[inline]
56 pub fn log_unmet_condition(mut self, level: log::Level, message: impl Into<String>) -> Self {
57 self.logger.set_unmet_condition(Some(level), message);
58 self
59 }
60
61 /// Configures logging when the prepare action fails.
62 #[inline]
63 pub fn log_prepare_failure(
64 mut self,
65 level: log::Level,
66 message_prefix: impl Into<String>,
67 ) -> Self {
68 self.logger.set_prepare_failure(Some(level), message_prefix);
69 self
70 }
71
72 /// Configures logging when the prepare commit action fails.
73 #[inline]
74 pub fn log_prepare_commit_failure(
75 mut self,
76 level: log::Level,
77 message_prefix: impl Into<String>,
78 ) -> Self {
79 self.logger
80 .set_prepare_commit_failure(Some(level), message_prefix);
81 self
82 }
83
84 /// Configures logging when the prepare rollback action fails.
85 #[inline]
86 pub fn log_prepare_rollback_failure(
87 mut self,
88 level: log::Level,
89 message_prefix: impl Into<String>,
90 ) -> Self {
91 self.logger
92 .set_prepare_rollback_failure(Some(level), message_prefix);
93 self
94 }
95
96 /// Configures the required double-checked condition.
97 ///
98 /// The tester is executed outside and inside the lock. State read by the
99 /// outside check must be safe to access without this executor's lock.
100 ///
101 /// # Parameters
102 ///
103 /// * `tester` - The reusable condition tester.
104 ///
105 /// # Returns
106 ///
107 /// The builder state that can configure prepare callbacks and build the
108 /// executor.
109 #[inline]
110 pub fn when<Tst>(self, tester: Tst) -> ExecutorReadyBuilder<L, T>
111 where
112 Tst: Tester + Send + Sync + 'static,
113 {
114 ExecutorReadyBuilder {
115 lock: self.lock,
116 tester: tester.into_arc(),
117 logger: self.logger,
118 prepare_action: None,
119 rollback_prepare_action: None,
120 commit_prepare_action: None,
121 _phantom: PhantomData,
122 }
123 }
124}