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);