qubit_function/consumers/bi_consumer/arc_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 `ArcBiConsumer` public type.
12
13use super::{
14 Arc,
15 ArcConditionalBiConsumer,
16 BiConsumer,
17 BiPredicate,
18 BoxBiConsumer,
19 BoxBiConsumerOnce,
20 RcBiConsumer,
21 ThreadSafeBiConsumerFn,
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
30// =======================================================================
31// 4. ArcBiConsumer - Thread-Safe Shared Ownership
32// =======================================================================
33
34/// ArcBiConsumer struct
35///
36/// A non-mutating bi-consumer implementation based on
37/// `Arc<dyn Fn(&T, &U) + Send + Sync>` for thread-safe shared ownership
38/// scenarios. The wrapper does not need `Mutex` because it only invokes a
39/// shared `Fn`.
40///
41/// # Features
42///
43/// - **Shared Ownership**: Cloneable via `Arc`, multiple owners allowed
44/// - **Thread-Safe**: Implements `Send + Sync`, safe for concurrent use
45/// - **Lock-free Wrapper**: No Mutex protection needed by the wrapper
46/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
47/// usable
48///
49/// # Use Cases
50///
51/// Choose `ArcBiConsumer` when:
52/// - Need to share non-mutating bi-consumer across multiple threads
53/// - Pure observation operations like logging, monitoring, notifications
54/// - Need high-concurrency reads without lock overhead
55///
56/// # Performance Advantages
57///
58/// Compared to `ArcStatefulBiConsumer`, `ArcBiConsumer` has no Mutex locking
59/// overhead, resulting in better performance in high-concurrency observation
60/// scenarios.
61///
62/// # Examples
63///
64/// ```rust
65/// use qubit_function::{BiConsumer, ArcBiConsumer};
66///
67/// let consumer = ArcBiConsumer::new(|x: &i32, y: &i32| {
68/// println!("Sum: {}", x + y);
69/// });
70/// let clone = consumer.clone();
71///
72/// consumer.accept(&5, &3);
73/// clone.accept(&10, &20);
74/// ```
75///
76pub struct ArcBiConsumer<T, U> {
77 pub(super) function: Arc<ThreadSafeBiConsumerFn<T, U>>,
78 pub(super) name: Option<String>,
79}
80
81impl<T, U> ArcBiConsumer<T, U> {
82 // Generates: new(), new_with_name(), name(), set_name(), noop()
83 impl_consumer_common_methods!(
84 ArcBiConsumer<T, U>,
85 (Fn(&T, &U) + Send + Sync + 'static),
86 |f| Arc::new(f)
87 );
88
89 // Generates: when() and and_then() methods that borrow &self (Arc can clone)
90 impl_shared_consumer_methods!(
91 ArcBiConsumer<T, U>,
92 ArcConditionalBiConsumer,
93 into_arc,
94 BiConsumer,
95 Send + Sync + 'static
96 );
97}
98
99impl<T, U> BiConsumer<T, U> for ArcBiConsumer<T, U> {
100 fn accept(&self, first: &T, second: &U) {
101 (self.function)(first, second)
102 }
103
104 // Use macro to implement conversion methods
105 impl_arc_conversions!(
106 ArcBiConsumer<T, U>,
107 BoxBiConsumer,
108 RcBiConsumer,
109 BoxBiConsumerOnce,
110 Fn(t: &T, u: &U)
111 );
112}
113
114// Use macro to generate Clone implementation
115impl_consumer_clone!(ArcBiConsumer<T, U>);
116
117// Use macro to generate Debug and Display implementations
118impl_consumer_debug_display!(ArcBiConsumer<T, U>);
119
120// =======================================================================
121// 5. Implement BiConsumer trait for closures
122// =======================================================================
123
124// Implements BiConsumer for all Fn(&T, &U)
125impl_closure_trait!(
126 BiConsumer<T, U>,
127 accept,
128 BoxBiConsumerOnce,
129 Fn(first: &T, second: &U)
130);