readonly_bi_consumer_demo/
readonly_bi_consumer_demo.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9
10//! ReadonlyBiConsumer demonstration
11//!
12//! This example demonstrates the usage of ReadonlyBiConsumer types, which
13//! neither modify their own state nor the input values.
14
15use prism3_function::{
16    ArcReadonlyBiConsumer, BoxReadonlyBiConsumer, RcReadonlyBiConsumer, ReadonlyBiConsumer,
17};
18use std::rc::Rc;
19use std::sync::{atomic::AtomicUsize, atomic::Ordering, Arc};
20use std::thread;
21
22fn main() {
23    println!("=== ReadonlyBiConsumer Demo ===\n");
24
25    // 1. BoxReadonlyBiConsumer - Single ownership
26    println!("1. BoxReadonlyBiConsumer - Single ownership:");
27    let box_consumer = BoxReadonlyBiConsumer::new(|x: &i32, y: &i32| {
28        println!("  Values: x={}, y={}, sum={}", x, y, x + y);
29    });
30    box_consumer.accept(&10, &5);
31    println!();
32
33    // 2. Method chaining with BoxReadonlyBiConsumer
34    println!("2. BoxReadonlyBiConsumer with method chaining:");
35    let chained = BoxReadonlyBiConsumer::new(|x: &i32, y: &i32| {
36        println!("  First operation: x={}, y={}", x, y);
37    })
38    .and_then(|x: &i32, y: &i32| {
39        println!("  Second operation: sum={}", x + y);
40    })
41    .and_then(|x: &i32, y: &i32| {
42        println!("  Third operation: product={}", x * y);
43    });
44    chained.accept(&5, &3);
45    println!();
46
47    // 3. ArcReadonlyBiConsumer - Thread-safe shared ownership
48    println!("3. ArcReadonlyBiConsumer - Thread-safe shared ownership:");
49    let counter = Arc::new(AtomicUsize::new(0));
50    let c = counter.clone();
51    let arc_consumer = ArcReadonlyBiConsumer::new(move |x: &i32, y: &i32| {
52        c.fetch_add(1, Ordering::SeqCst);
53        println!("  Thread {:?}: sum={}", thread::current().id(), x + y);
54    });
55
56    let consumer1 = arc_consumer.clone();
57    let consumer2 = arc_consumer.clone();
58
59    let handle1 = thread::spawn(move || {
60        consumer1.accept(&10, &5);
61    });
62
63    let handle2 = thread::spawn(move || {
64        consumer2.accept(&20, &8);
65    });
66
67    handle1.join().unwrap();
68    handle2.join().unwrap();
69    println!("  Total calls: {}\n", counter.load(Ordering::SeqCst));
70
71    // 4. RcReadonlyBiConsumer - Single-threaded shared ownership
72    println!("4. RcReadonlyBiConsumer - Single-threaded shared ownership:");
73    let counter = Rc::new(std::cell::Cell::new(0));
74    let c = counter.clone();
75    let rc_consumer = RcReadonlyBiConsumer::new(move |x: &i32, y: &i32| {
76        c.set(c.get() + 1);
77        println!("  Call {}: sum={}", c.get(), x + y);
78    });
79
80    let clone1 = rc_consumer.clone();
81    let clone2 = rc_consumer.clone();
82
83    clone1.accept(&5, &3);
84    clone2.accept(&7, &2);
85    println!("  Total calls: {}\n", counter.get());
86
87    // 5. Working with closures directly
88    println!("5. Working with closures directly:");
89    let closure = |x: &i32, y: &i32| {
90        println!("  x={}, y={}, product={}", x, y, x * y);
91    };
92    closure.accept(&10, &20);
93    println!();
94
95    // 6. Pure observation - logging
96    println!("6. Pure observation - logging:");
97    let logger = BoxReadonlyBiConsumer::new(|x: &i32, y: &i32| {
98        println!("  [LOG] Processing pair: ({}, {})", x, y);
99    });
100    logger.accept(&5, &3);
101    logger.accept(&10, &7);
102    println!();
103
104    // 7. Chaining observations
105    println!("7. Chaining observations:");
106    let log_input = BoxReadonlyBiConsumer::new(|x: &i32, y: &i32| {
107        println!("  [INPUT] x={}, y={}", x, y);
108    });
109    let log_sum = BoxReadonlyBiConsumer::new(|x: &i32, y: &i32| {
110        println!("  [SUM] {}", x + y);
111    });
112    let log_product = BoxReadonlyBiConsumer::new(|x: &i32, y: &i32| {
113        println!("  [PRODUCT] {}", x * y);
114    });
115
116    let chained = log_input.and_then(log_sum).and_then(log_product);
117    chained.accept(&5, &3);
118    println!();
119
120    // 8. ArcReadonlyBiConsumer - Reusability
121    println!("8. ArcReadonlyBiConsumer - Reusability:");
122    let first = ArcReadonlyBiConsumer::new(|x: &i32, y: &i32| {
123        println!("  First: x={}, y={}", x, y);
124    });
125    let second = ArcReadonlyBiConsumer::new(|x: &i32, y: &i32| {
126        println!("  Second: sum={}", x + y);
127    });
128
129    // Both first and second can be reused after chaining
130    let chained1 = first.and_then(&second);
131    let chained2 = first.and_then(&second);
132
133    println!("  Using chained1:");
134    chained1.accept(&5, &3);
135
136    println!("  Using chained2:");
137    chained2.accept(&10, &2);
138    println!();
139
140    // 9. Name support
141    println!("9. Name support:");
142    let mut named_consumer = BoxReadonlyBiConsumer::<i32, i32>::noop();
143    println!("  Initial name: {:?}", named_consumer.name());
144
145    named_consumer.set_name("sum_logger");
146    println!("  After setting name: {:?}", named_consumer.name());
147    println!("  Display: {}\n", named_consumer);
148
149    // 10. No-op consumer
150    println!("10. No-op consumer:");
151    let noop = BoxReadonlyBiConsumer::<i32, i32>::noop();
152    noop.accept(&42, &10);
153    println!("  No-op completed (no output expected)\n");
154
155    println!("=== Demo Complete ===");
156}