Skip to main content

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