Skip to main content

qubit_dcl/double_checked/
double_checked_lock.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//! # Double-Checked Lock Convenience API
11//!
12//! Provides a one-shot convenience wrapper around
13//! [`super::DoubleCheckedLockExecutor`].
14//!
15
16use super::{
17    DoubleCheckedLockBuilder,
18    DoubleCheckedLockExecutor,
19};
20use qubit_lock::Lock;
21
22/// Entry type for one-shot double-checked lock execution.
23///
24/// This API is useful when you do not need to keep a reusable executor
25/// instance. It delegates to [`DoubleCheckedLockExecutor`] internally.
26///
27/// # Examples
28///
29/// ```rust
30/// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
31///
32/// use qubit_dcl::{ArcMutex, DoubleCheckedLock, Lock};
33///
34/// let data = ArcMutex::new(10);
35/// let skip = Arc::new(AtomicBool::new(false));
36///
37/// let result = DoubleCheckedLock::on(data.clone())
38///     .when({
39///         let skip = skip.clone();
40///         move || !skip.load(Ordering::Acquire)
41///     })
42///     .call_with(|value: &mut i32| {
43///         *value += 5;
44///         Ok::<i32, std::io::Error>(*value)
45///     })
46///     .get_result();
47///
48/// assert!(result.is_success());
49/// assert_eq!(data.read(|value| *value), 15);
50/// ```
51#[derive(Debug, Clone, Copy, Default)]
52pub struct DoubleCheckedLock;
53
54impl DoubleCheckedLock {
55    /// Starts one-shot double-checked lock configuration by attaching a lock.
56    ///
57    /// # Parameters
58    ///
59    /// * `lock` - Lock handle protecting the data used by the one-shot
60    ///   execution.
61    ///
62    /// # Returns
63    ///
64    /// A convenience builder that can configure the double-checked condition.
65    #[inline]
66    #[must_use = "assign or chain the returned builder"]
67    pub fn on<L, T>(lock: L) -> DoubleCheckedLockBuilder<L, T>
68    where
69        L: Lock<T>,
70    {
71        DoubleCheckedLockBuilder {
72            inner: DoubleCheckedLockExecutor::builder().on(lock),
73        }
74    }
75}