Skip to main content

qubit_function/functions/stateful_mutating_function/
arc_stateful_mutating_function.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 `ArcStatefulMutatingFunction` public type.
12
13use super::{
14    Arc,
15    ArcConditionalStatefulMutatingFunction,
16    ArcStatefulMutatingFunctionFn,
17    BoxMutatingFunctionOnce,
18    BoxStatefulMutatingFunction,
19    Function,
20    Mutex,
21    Predicate,
22    RcStatefulMutatingFunction,
23    StatefulMutatingFunction,
24    impl_arc_conversions,
25    impl_function_clone,
26    impl_function_common_methods,
27    impl_function_debug_display,
28    impl_function_identity_method,
29    impl_shared_function_methods,
30};
31
32// =======================================================================
33// 5. ArcStatefulMutatingFunction - Thread-Safe Shared Ownership
34// =======================================================================
35
36/// ArcStatefulMutatingFunction struct
37///
38/// A stateful mutating function implementation based on
39/// `Arc<Mutex<dyn FnMut(&mut T) -> R + Send>>` for thread-safe shared
40/// ownership scenarios. This type allows the function to be safely shared
41/// and used across multiple threads.
42///
43/// # Features
44///
45/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
46/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
47/// - **Stateful**: Can modify captured environment (uses `FnMut`)
48/// - **Chainable**: Method chaining via `&self` (non-consuming)
49///
50/// # Use Cases
51///
52/// Choose `ArcStatefulMutatingFunction` when:
53/// - The function needs to be shared across multiple threads for stateful
54///   operations
55/// - Concurrent task processing (e.g., thread pools)
56/// - Thread safety is required (Send + Sync)
57///
58/// # Examples
59///
60/// ```rust
61/// use qubit_function::{StatefulMutatingFunction,
62///                       ArcStatefulMutatingFunction};
63///
64/// let counter = {
65///     let mut count = 0;
66///     ArcStatefulMutatingFunction::new(move |x: &mut i32| {
67///         count += 1;
68///         *x *= 2;
69///         count
70///     })
71/// };
72/// let mut clone = counter.clone();
73///
74/// let mut value = 5;
75/// assert_eq!(clone.apply(&mut value), 1);
76/// ```
77///
78pub struct ArcStatefulMutatingFunction<T, R> {
79    pub(super) function: ArcStatefulMutatingFunctionFn<T, R>,
80    pub(super) name: Option<String>,
81}
82
83impl<T, R> ArcStatefulMutatingFunction<T, R> {
84    // Generates: new(), new_with_name(), new_with_optional_name(), name(), set_name()
85    impl_function_common_methods!(
86        ArcStatefulMutatingFunction<T, R>,
87        (FnMut(&mut T) -> R + Send + 'static),
88        |f| Arc::new(Mutex::new(f))
89    );
90
91    // Generates: when(), and_then(), compose()
92    impl_shared_function_methods!(
93        ArcStatefulMutatingFunction<T, R>,
94        ArcConditionalStatefulMutatingFunction,
95        into_arc,
96        Function,  // chains a non-mutating function after this mutating function
97        Send + Sync + 'static
98    );
99}
100
101// Generates: Clone implementation for ArcStatefulMutatingFunction<T, R>
102impl_function_clone!(ArcStatefulMutatingFunction<T, R>);
103
104// Generates: Debug and Display implementations for ArcStatefulMutatingFunction<T, R>
105impl_function_debug_display!(ArcStatefulMutatingFunction<T, R>);
106
107// Generates: identity() method for ArcStatefulMutatingFunction<T, T>
108impl_function_identity_method!(ArcStatefulMutatingFunction<T, T>, mutating);
109
110// Implement StatefulMutatingFunction trait for ArcStatefulMutatingFunction<T, R>
111impl<T, R> StatefulMutatingFunction<T, R> for ArcStatefulMutatingFunction<T, R> {
112    fn apply(&mut self, t: &mut T) -> R {
113        (self.function.lock())(t)
114    }
115
116    // Use macro to implement conversion methods
117    impl_arc_conversions!(
118        ArcStatefulMutatingFunction<T, R>,
119        BoxStatefulMutatingFunction,
120        RcStatefulMutatingFunction,
121        BoxMutatingFunctionOnce,
122        FnMut(input: &mut T) -> R
123    );
124}
125
126// =======================================================================
127// 6. Implement StatefulMutatingFunction trait for closures
128// =======================================================================
129
130impl<T, R, F> StatefulMutatingFunction<T, R> for F
131where
132    F: FnMut(&mut T) -> R,
133{
134    fn apply(&mut self, input: &mut T) -> R {
135        self(input)
136    }
137
138    fn into_box(self) -> BoxStatefulMutatingFunction<T, R>
139    where
140        Self: Sized + 'static,
141    {
142        BoxStatefulMutatingFunction::new(self)
143    }
144
145    fn into_rc(self) -> RcStatefulMutatingFunction<T, R>
146    where
147        Self: Sized + 'static,
148    {
149        RcStatefulMutatingFunction::new(self)
150    }
151
152    fn into_arc(self) -> ArcStatefulMutatingFunction<T, R>
153    where
154        Self: Sized + Send + 'static,
155    {
156        ArcStatefulMutatingFunction::new(self)
157    }
158
159    fn into_fn(self) -> impl FnMut(&mut T) -> R
160    where
161        Self: Sized + 'static,
162    {
163        self
164    }
165
166    fn to_box(&self) -> BoxStatefulMutatingFunction<T, R>
167    where
168        Self: Sized + Clone + 'static,
169    {
170        let cloned = self.clone();
171        BoxStatefulMutatingFunction::new(cloned)
172    }
173
174    fn to_rc(&self) -> RcStatefulMutatingFunction<T, R>
175    where
176        Self: Sized + Clone + 'static,
177    {
178        let cloned = self.clone();
179        RcStatefulMutatingFunction::new(cloned)
180    }
181
182    fn to_arc(&self) -> ArcStatefulMutatingFunction<T, R>
183    where
184        Self: Sized + Clone + Send + 'static,
185    {
186        let cloned = self.clone();
187        ArcStatefulMutatingFunction::new(cloned)
188    }
189
190    fn to_fn(&self) -> impl FnMut(&mut T) -> R
191    where
192        Self: Sized + Clone + 'static,
193    {
194        self.clone()
195    }
196
197    fn into_once(self) -> BoxMutatingFunctionOnce<T, R>
198    where
199        Self: Sized + 'static,
200    {
201        BoxMutatingFunctionOnce::new(self)
202    }
203
204    fn to_once(&self) -> BoxMutatingFunctionOnce<T, R>
205    where
206        Self: Sized + Clone + 'static,
207    {
208        BoxMutatingFunctionOnce::new(self.clone())
209    }
210}