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!((Fn() -> T + Send + Sync + 'static), |f| Arc::new(f), "supplier");
102
103 crate::macros::impl_common_name_methods!("supplier");
104
105 // Generates: map(), filter(), zip()
106 impl_shared_supplier_methods!(ArcSupplier<T>, Supplier, (arc));
107}
108
109// Separate impl block for constant() with stricter T: Sync bound
110impl<T> ArcSupplier<T> {
111 /// Creates a supplier that returns a constant value.
112 ///
113 /// Creates a supplier that always returns the same value. Useful for
114 /// default values or placeholder implementations.
115 ///
116 /// **Note:** This method requires `T: Sync` because the constant value
117 /// is captured by a `Fn` closure which needs to be `Sync` for `Arc`.
118 ///
119 /// # Parameters
120 ///
121 /// * `value` - The constant value to return
122 ///
123 /// # Returns
124 ///
125 /// Returns a new supplier instance that returns the constant value.
126 ///
127 /// # Examples
128 ///
129 /// ```rust
130 /// use qubit_function::{ArcSupplier, Supplier};
131 ///
132 /// let supplier = ArcSupplier::constant(42);
133 /// assert_eq!(supplier.get(), 42);
134 /// assert_eq!(supplier.get(), 42); // Can be called multiple times
135 /// ```
136 pub fn constant(value: T) -> Self
137 where
138 T: Clone + Send + Sync + 'static,
139 {
140 Self::new(move || value.clone())
141 }
142}
143
144// Generates: Debug and Display implementations for ArcSupplier<T>
145impl_supplier_debug_display!(ArcSupplier<T>);
146
147// Generates: Clone implementation for ArcSupplier<T>
148impl_supplier_clone!(ArcSupplier<T>);
149
150impl<T> Supplier<T> for ArcSupplier<T> {
151 fn get(&self) -> T {
152 (self.function)()
153 }
154
155 // Use macro to implement conversion methods
156 impl_arc_conversions!(
157 ArcSupplier<T>,
158 BoxSupplier,
159 RcSupplier,
160 BoxSupplierOnce,
161 Fn() -> T
162 );
163}