qubit_function/tasks/callable/rc_callable.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026.
4 * Haixing Hu, Qubit Co. Ltd.
5 *
6 * All rights reserved.
7 *
8 ******************************************************************************/
9//! Defines the `RcCallable` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// RcCallable
17// ============================================================================
18
19/// Single-threaded shared callable.
20///
21/// `RcCallable<R, E>` stores a `Rc<RefCell<dyn FnMut() -> Result<R, E>>>` and
22/// can be called repeatedly through shared ownership.
23///
24/// # Type Parameters
25///
26/// * `R` - The success value returned by the computation.
27/// * `E` - The error value returned when the computation fails.
28///
29/// # Author
30///
31/// Haixing Hu
32pub struct RcCallable<R, E> {
33 /// The stateful closure executed by this callable.
34 pub(super) function: Rc<RefCell<dyn FnMut() -> Result<R, E>>>,
35 /// The optional name of this callable.
36 pub(super) name: Option<String>,
37}
38
39impl<R, E> Clone for RcCallable<R, E> {
40 #[inline]
41 fn clone(&self) -> Self {
42 Self {
43 function: Rc::clone(&self.function),
44 name: self.name.clone(),
45 }
46 }
47}
48
49impl<R, E> RcCallable<R, E> {
50 impl_common_new_methods!(
51 (FnMut() -> Result<R, E> + 'static),
52 |function| Rc::new(RefCell::new(function)),
53 "callable"
54 );
55
56 /// Creates an `RcCallable` from a reusable supplier.
57 ///
58 /// # Parameters
59 ///
60 /// * `supplier` - The supplier that produces the callable result.
61 ///
62 /// # Returns
63 ///
64 /// A new `RcCallable<R, E>`.
65 #[inline]
66 pub fn from_supplier<S>(supplier: S) -> Self
67 where
68 S: Supplier<Result<R, E>> + 'static,
69 {
70 Self::new(move || supplier.get())
71 }
72
73 impl_common_name_methods!("callable");
74}
75
76impl<R, E> Callable<R, E> for RcCallable<R, E> {
77 /// Executes the shared callable.
78 #[inline]
79 fn call(&mut self) -> Result<R, E> {
80 (self.function.borrow_mut())()
81 }
82
83 impl_rc_conversions!(
84 RcCallable<R, E>,
85 BoxCallable,
86 BoxCallableOnce,
87 FnMut() -> Result<R, E>
88 );
89
90 /// Converts this shared callable into a boxed runnable while preserving its
91 /// name.
92 #[inline]
93 fn into_runnable(self) -> BoxRunnable<E>
94 where
95 Self: Sized + 'static,
96 {
97 let name = self.name;
98 let function = self.function;
99 BoxRunnable::new_with_optional_name(move || (function.borrow_mut())().map(|_| ()), name)
100 }
101}