Skip to main content

qubit_function/tasks/callable_with/
arc_callable_with.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 `ArcCallableWith` public type.
12
13use std::sync::Arc;
14
15use parking_lot::Mutex;
16
17use crate::{
18    functions::macros::impl_function_debug_display,
19    macros::{
20        impl_arc_conversions,
21        impl_closure_trait,
22        impl_common_name_methods,
23        impl_common_new_methods,
24    },
25    tasks::{
26        callable_with::{
27            BoxCallableWith,
28            CallableWith,
29            RcCallableWith,
30        },
31        runnable_with::BoxRunnableWith,
32    },
33};
34
35type ArcCallableWithFn<T, R, E> = Arc<Mutex<dyn FnMut(&mut T) -> Result<R, E> + Send>>;
36
37/// Thread-safe shared callable with mutable input.
38///
39/// `ArcCallableWith<T, R, E>` stores an
40/// `Arc<Mutex<dyn FnMut(&mut T) -> Result<R, E> + Send>>`.
41///
42pub struct ArcCallableWith<T, R, E> {
43    /// The stateful closure executed by this callable.
44    pub(super) function: ArcCallableWithFn<T, R, E>,
45    /// The optional name of this callable.
46    pub(super) name: Option<String>,
47}
48
49impl<T, R, E> Clone for ArcCallableWith<T, R, E> {
50    #[inline]
51    fn clone(&self) -> Self {
52        Self {
53            function: Arc::clone(&self.function),
54            name: self.name.clone(),
55        }
56    }
57}
58
59impl<T, R, E> ArcCallableWith<T, R, E> {
60    impl_common_new_methods!(
61        (FnMut(&mut T) -> Result<R, E> + Send + 'static),
62        |function| Arc::new(Mutex::new(function)),
63        "callable-with"
64    );
65
66    impl_common_name_methods!("callable-with");
67}
68
69impl<T, R, E> CallableWith<T, R, E> for ArcCallableWith<T, R, E> {
70    /// Executes the thread-safe callable with mutable input.
71    #[inline]
72    fn call_with(&mut self, input: &mut T) -> Result<R, E> {
73        (self.function.lock())(input)
74    }
75
76    impl_arc_conversions!(
77        ArcCallableWith<T, R, E>,
78        BoxCallableWith,
79        RcCallableWith,
80        FnMut(input: &mut T) -> Result<R, E>
81    );
82
83    /// Converts this shared callable into a boxed runnable while preserving its
84    /// name.
85    #[inline]
86    fn into_runnable_with(self) -> BoxRunnableWith<T, E>
87    where
88        Self: Sized + 'static,
89    {
90        let name = self.name;
91        let function = self.function;
92        BoxRunnableWith::new_with_optional_name(
93            move |input| (function.lock())(input).map(|_| ()),
94            name,
95        )
96    }
97}
98
99impl_closure_trait!(
100    CallableWith<T, R, E>,
101    call_with,
102    FnMut(input: &mut T) -> Result<R, E>
103);
104
105impl_function_debug_display!(BoxCallableWith<T, R, E>);
106impl_function_debug_display!(RcCallableWith<T, R, E>);
107impl_function_debug_display!(ArcCallableWith<T, R, E>);