Skip to main content

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