Skip to main content

qubit_function/consumers/stateful_consumer/
arc_stateful_consumer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `ArcStatefulConsumer` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// 4. ArcStatefulConsumer - Thread-Safe Shared Ownership Implementation
17// ============================================================================
18
19/// ArcStatefulConsumer struct
20///
21/// Consumer implementation based on `Arc<Mutex<dyn FnMut(&T) + Send>>` for
22/// thread-safe shared ownership scenarios. This consumer can be safely cloned
23/// and shared across multiple threads.
24///
25/// # Features
26///
27/// - **Shared Ownership**: Cloneable through `Arc`, allowing multiple owners
28/// - **Thread Safety**: Implements `Send + Sync`, safe for concurrent use
29/// - **Interior Mutability**: Uses `Mutex` for safe mutable access
30/// - **Non-Consuming API**: `and_then` borrows `&self`, original object remains
31///   usable
32/// - **Cross-Thread Sharing**: Can be sent to other threads and used
33///
34/// # Use Cases
35///
36/// Choose `ArcStatefulConsumer` when:
37/// - Need to share consumers across multiple threads
38/// - Concurrent task processing (e.g., thread pools)
39/// - Using the same consumer in multiple places simultaneously
40/// - Need thread safety (Send + Sync)
41///
42/// # Performance Considerations
43///
44/// `ArcStatefulConsumer` has some performance overhead compared to `BoxStatefulConsumer`:
45/// - **Reference Counting**: Atomic operations on clone/drop
46/// - **Mutex Locking**: Each `accept` call requires lock acquisition
47/// - **Lock Contention**: High concurrency may cause contention
48///
49/// These overheads are necessary for safe concurrent access. If thread safety
50/// is not needed, consider using `RcStatefulConsumer` for less single-threaded sharing
51/// overhead.
52///
53/// # Examples
54///
55/// ```rust
56/// use qubit_function::{Consumer, StatefulConsumer, ArcStatefulConsumer};
57/// use std::sync::{Arc, Mutex};
58///
59/// let log = Arc::new(Mutex::new(Vec::new()));
60/// let l = log.clone();
61/// let mut consumer = ArcStatefulConsumer::new(move |x: &i32| {
62///     l.lock().unwrap().push(*x * 2);
63/// });
64/// let mut clone = consumer.clone();
65///
66/// consumer.accept(&5);
67/// assert_eq!(*log.lock().unwrap(), vec![10]);
68/// ```
69///
70/// # Author
71///
72/// Haixing Hu
73pub struct ArcStatefulConsumer<T> {
74    pub(super) function: Arc<Mutex<dyn FnMut(&T) + Send>>,
75    pub(super) name: Option<String>,
76}
77
78impl<T> ArcStatefulConsumer<T> {
79    // Generates: new(), new_with_name(), name(), set_name(), noop()
80    impl_consumer_common_methods!(ArcStatefulConsumer<T>, (FnMut(&T) + Send + 'static), |f| {
81        Arc::new(Mutex::new(f))
82    });
83
84    // Generates: when() and and_then() methods that borrow &self (Arc can clone)
85    impl_shared_consumer_methods!(
86        ArcStatefulConsumer<T>,
87        ArcConditionalStatefulConsumer,
88        into_arc,
89        StatefulConsumer,
90        Send + Sync + 'static
91    );
92}
93
94impl<T> StatefulConsumer<T> for ArcStatefulConsumer<T> {
95    fn accept(&mut self, value: &T) {
96        (self.function.lock())(value)
97    }
98
99    // Use macro to implement conversion methods
100    impl_arc_conversions!(
101        ArcStatefulConsumer<T>,
102        BoxStatefulConsumer,
103        RcStatefulConsumer,
104        BoxConsumerOnce,
105        FnMut(t: &T)
106    );
107}
108
109// Use macro to generate Clone implementation
110impl_consumer_clone!(ArcStatefulConsumer<T>);
111
112// Use macro to generate Debug and Display implementations
113impl_consumer_debug_display!(ArcStatefulConsumer<T>);
114
115// ============================================================================
116// 5. Implement Consumer trait for closures
117// ============================================================================
118
119// Implement Consumer for all FnMut(&T)
120impl_closure_trait!(
121    StatefulConsumer<T>,
122    accept,
123    BoxConsumerOnce,
124    FnMut(value: &T)
125);