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