Skip to main content

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