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}