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