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