Skip to main content

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}