qubit_function/consumers/bi_consumer/rc_bi_consumer.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `RcBiConsumer` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// =======================================================================
16// 3. RcBiConsumer - Single-Threaded Shared Ownership
17// =======================================================================
18
19/// RcBiConsumer struct
20///
21/// A non-mutating bi-consumer implementation based on `Rc<dyn Fn(&T, &U)>`
22/// for single-threaded shared ownership scenarios. The wrapper does not need
23/// `RefCell` because it only invokes a shared `Fn`.
24///
25/// # Features
26///
27/// - **Shared Ownership**: Cloneable via `Rc`, multiple owners allowed
28/// - **Single-Threaded**: Not thread-safe, cannot send across threads
29/// - **No Wrapper Interior Mutability Overhead**: No RefCell needed by the
30/// wrapper
31/// - **Non-Consuming API**: `and_then` borrows `&self`, original remains
32/// usable
33///
34/// # Use Cases
35///
36/// Choose `RcBiConsumer` when:
37/// - Need to share non-mutating bi-consumer within a single thread
38/// - Pure observation operations, performance critical
39/// - Single-threaded UI framework event handling
40///
41/// # Performance Advantages
42///
43/// `RcBiConsumer` has neither Arc's atomic operation overhead nor
44/// RefCell's runtime borrow checking overhead, making it the best
45/// performing among the three non-mutating bi-consumer types.
46///
47/// # Examples
48///
49/// ```rust
50/// use qubit_function::{BiConsumer, RcBiConsumer};
51///
52/// let consumer: RcBiConsumer<i32, i32> = RcBiConsumer::new(|x: &i32, y: &i32| {
53/// println!("Sum: {}", x + y);
54/// });
55/// let clone = consumer.clone();
56///
57/// consumer.accept(&5, &3);
58/// clone.accept(&10, &20);
59/// ```
60///
61/// # Author
62///
63/// Haixing Hu
64pub struct RcBiConsumer<T, U> {
65 pub(super) function: Rc<BiConsumerFn<T, U>>,
66 pub(super) name: Option<String>,
67}
68
69impl<T, U> RcBiConsumer<T, U> {
70 // Generates: new(), new_with_name(), name(), set_name(), noop()
71 impl_consumer_common_methods!(
72 RcBiConsumer<T, U>,
73 (Fn(&T, &U) + 'static),
74 |f| Rc::new(f)
75 );
76
77 // Generates: when() and and_then() methods that borrow &self (Rc can clone)
78 impl_shared_consumer_methods!(
79 RcBiConsumer<T, U>,
80 RcConditionalBiConsumer,
81 into_rc,
82 BiConsumer,
83 'static
84 );
85}
86
87impl<T, U> BiConsumer<T, U> for RcBiConsumer<T, U> {
88 fn accept(&self, first: &T, second: &U) {
89 (self.function)(first, second)
90 }
91
92 // Use macro to implement conversion methods
93 impl_rc_conversions!(
94 RcBiConsumer<T, U>,
95 BoxBiConsumer,
96 BoxBiConsumerOnce,
97 Fn(t: &T, u: &U)
98 );
99}
100
101// Use macro to generate Clone implementation
102impl_consumer_clone!(RcBiConsumer<T, U>);
103
104// Use macro to generate Debug and Display implementations
105impl_consumer_debug_display!(RcBiConsumer<T, U>);