Skip to main content

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