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