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