Skip to main content

qubit_function/suppliers/supplier/
arc_supplier.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// qubit-style: allow explicit-imports
11//! Defines the `ArcSupplier` public type.
12
13use super::{
14    Arc,
15    BoxSupplier,
16    BoxSupplierOnce,
17    Predicate,
18    RcSupplier,
19    Supplier,
20    Transformer,
21    impl_arc_conversions,
22    impl_shared_supplier_methods,
23    impl_supplier_clone,
24    impl_supplier_debug_display,
25};
26
27// ======================================================================
28// ArcSupplier - Thread-safe Shared Ownership Implementation
29// ======================================================================
30
31/// Thread-safe shared ownership stateless supplier.
32///
33/// Uses `Arc<dyn Fn() -> T + Send + Sync>` for thread-safe shared
34/// ownership. **Lock-free** - no `Mutex` needed! Can be cloned and
35/// sent across threads with excellent concurrent performance.
36///
37/// # Ownership Model
38///
39/// Methods borrow `&self` instead of consuming `self`. The
40/// original supplier remains usable after method calls:
41///
42/// ```rust
43/// use qubit_function::{ArcSupplier, Supplier};
44///
45/// let source = ArcSupplier::new(|| 10);
46/// let mapped = source.map(|x| x * 2);
47/// // source is still usable here!
48/// ```
49///
50/// # Lock-Free Performance
51///
52/// Unlike `ArcStatefulSupplier`, this implementation doesn't need `Mutex`.
53/// Multiple threads can call `get()` concurrently without lock
54/// contention, making it ideal for high-concurrency scenarios.
55///
56/// # Examples
57///
58/// ## Thread-safe Factory
59///
60/// ```rust
61/// use qubit_function::{ArcSupplier, Supplier};
62/// use std::thread;
63///
64/// let factory = ArcSupplier::new(|| {
65///     String::from("Hello")
66/// });
67///
68/// let f1 = factory.clone();
69/// let f2 = factory.clone();
70///
71/// let h1 = thread::spawn(move || f1.get());
72/// let h2 = thread::spawn(move || f2.get());
73///
74/// assert_eq!(h1.join().expect("thread should not panic"), "Hello");
75/// assert_eq!(h2.join().expect("thread should not panic"), "Hello");
76/// ```
77///
78/// ## Reusable Transformations
79///
80/// ```rust
81/// use qubit_function::{ArcSupplier, Supplier};
82///
83/// let base = ArcSupplier::new(|| 10);
84/// let doubled = base.map(|x| x * 2);
85/// let tripled = base.map(|x| x * 3);
86///
87/// // All remain usable
88/// assert_eq!(base.get(), 10);
89/// assert_eq!(doubled.get(), 20);
90/// assert_eq!(tripled.get(), 30);
91/// ```
92///
93pub struct ArcSupplier<T> {
94    pub(super) function: Arc<dyn Fn() -> T + Send + Sync>,
95    pub(super) name: Option<String>,
96}
97
98impl<T> ArcSupplier<T> {
99    // Generates: new(), new_with_name(), name(), set_name()
100    // Note: constant() is NOT generated here, implemented separately below
101    crate::macros::impl_common_new_methods!(
102        (Fn() -> T + Send + Sync + 'static),
103        |f| Arc::new(f),
104        "supplier"
105    );
106
107    crate::macros::impl_common_name_methods!("supplier");
108
109    // Generates: map(), filter(), zip()
110    impl_shared_supplier_methods!(ArcSupplier<T>, Supplier, (arc));
111}
112
113// Separate impl block for constant() with stricter T: Sync bound
114impl<T> ArcSupplier<T> {
115    /// Creates a supplier that returns a constant value.
116    ///
117    /// Creates a supplier that always returns the same value. Useful for
118    /// default values or placeholder implementations.
119    ///
120    /// **Note:** This method requires `T: Sync` because the constant value
121    /// is captured by a `Fn` closure which needs to be `Sync` for `Arc`.
122    ///
123    /// # Parameters
124    ///
125    /// * `value` - The constant value to return
126    ///
127    /// # Returns
128    ///
129    /// Returns a new supplier instance that returns the constant value.
130    ///
131    /// # Examples
132    ///
133    /// ```rust
134    /// use qubit_function::{ArcSupplier, Supplier};
135    ///
136    /// let supplier = ArcSupplier::constant(42);
137    /// assert_eq!(supplier.get(), 42);
138    /// assert_eq!(supplier.get(), 42); // Can be called multiple times
139    /// ```
140    pub fn constant(value: T) -> Self
141    where
142        T: Clone + Send + Sync + 'static,
143    {
144        Self::new(move || value.clone())
145    }
146}
147
148// Generates: Debug and Display implementations for ArcSupplier<T>
149impl_supplier_debug_display!(ArcSupplier<T>);
150
151// Generates: Clone implementation for ArcSupplier<T>
152impl_supplier_clone!(ArcSupplier<T>);
153
154impl<T> Supplier<T> for ArcSupplier<T> {
155    fn get(&self) -> T {
156        (self.function)()
157    }
158
159    // Use macro to implement conversion methods
160    impl_arc_conversions!(
161        ArcSupplier<T>,
162        BoxSupplier,
163        RcSupplier,
164        BoxSupplierOnce,
165        Fn() -> T
166    );
167}