Skip to main content

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}