qubit_function/tasks/callable/arc_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 `ArcCallable` public type.
10
11#![allow(unused_imports)]
12
13use super::*;
14
15// ============================================================================
16// ArcCallable
17// ============================================================================
18
19/// Thread-safe callable.
20///
21/// `ArcCallable<R, E>` stores a `Arc<Mutex<dyn FnMut() -> Result<R, E> + Send>>`
22/// and can be called repeatedly across threads.
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 ArcCallable<R, E> {
33 /// The stateful closure executed by this callable.
34 pub(super) function: Arc<Mutex<dyn FnMut() -> Result<R, E> + Send>>,
35 /// The optional name of this callable.
36 pub(super) name: Option<String>,
37}
38
39impl<R, E> Clone for ArcCallable<R, E> {
40 #[inline]
41 fn clone(&self) -> Self {
42 Self {
43 function: Arc::clone(&self.function),
44 name: self.name.clone(),
45 }
46 }
47}
48
49impl<R, E> ArcCallable<R, E> {
50 impl_common_new_methods!(
51 (FnMut() -> Result<R, E> + Send + 'static),
52 |function| Arc::new(Mutex::new(function)),
53 "callable"
54 );
55
56 /// Creates an `ArcCallable` from a reusable supplier.
57 ///
58 /// # Parameters
59 ///
60 /// * `supplier` - The supplier that produces the callable result.
61 ///
62 /// # Returns
63 ///
64 /// A new `ArcCallable<R, E>`.
65 #[inline]
66 pub fn from_supplier<S>(supplier: S) -> Self
67 where
68 S: Supplier<Result<R, E>> + Send + '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 ArcCallable<R, E> {
77 /// Executes the thread-safe callable.
78 #[inline]
79 fn call(&mut self) -> Result<R, E> {
80 (self.function.lock())()
81 }
82
83 impl_arc_conversions!(
84 ArcCallable<R, E>,
85 BoxCallable,
86 RcCallable,
87 BoxCallableOnce,
88 FnMut() -> Result<R, E>
89 );
90
91 /// Converts this shared callable into a boxed runnable while preserving its
92 /// name.
93 #[inline]
94 fn into_runnable(self) -> BoxRunnable<E>
95 where
96 Self: Sized + 'static,
97 {
98 let name = self.name;
99 let function = self.function;
100 BoxRunnable::new_with_optional_name(move || (function.lock())().map(|_| ()), name)
101 }
102}
103
104impl_closure_trait!(
105 Callable<R, E>,
106 call,
107 BoxCallableOnce,
108 FnMut() -> Result<R, E>
109);
110
111impl_function_debug_display!(BoxCallable<R, E>);
112impl_function_debug_display!(RcCallable<R, E>);
113impl_function_debug_display!(ArcCallable<R, E>);