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