Sync function to async function conversion

Hello,

Here is my code:

use std::{
    future::Future,
    pin::Pin,
    sync::{Arc, Mutex},
};

use async_trait::async_trait;

fn main() {}

pub fn main_sync(
    ob: &impl ObImpl,
    path: String,
    value: Arc<Value>,
) -> Arc<Mutex<dyn FnMut(&dyn ObImpl, String, Arc<Value>) + Send + Sync>> {
    Arc::new(Mutex::new(
        move |ob: &dyn ObImpl, path: String, value: Arc<Value>| {},
    ))
}

pub async fn main_async(
    ob: &impl ObImplAsync,
    path: String,
    value: Arc<Value>,
) -> Arc<
    Mutex<
        Box<
            dyn FnOnce(
                    &'static dyn ObImplAsync,
                    String,
                    Arc<Value>,
                ) -> Pin<Box<dyn Future<Output = ()>>>
                + Send
                + Sync,
        >,
    >,
> {
    Arc::new(Mutex::new(Box::new(
        move |ob: &'static dyn ObImplAsync, path: String, value: Arc<Value>| {
            Box::pin(async move {}) as Pin<Box<dyn Future<Output = ()>>>
        },
    )))
}

pub trait ObImpl {
    fn syncfn(&self, path: String, value: Arc<Value>) -> Option<Arc<Value>>;
}

#[async_trait]
pub trait ObImplAsync {
    async fn asyncfn(&self, path: String, value: Arc<Value>) -> Option<Arc<Value>>;
}

pub struct Value {
    a: i32,
}

pub struct Ob {
    fn_sync:
        Arc<Mutex<Option<Arc<Mutex<dyn FnMut(&dyn ObImpl, String, Arc<Value>) + Send + Sync>>>>>,
    fn_async: Arc<
        Mutex<
            Option<
                Arc<
                    Mutex<
                        Box<
                            dyn FnOnce(
                                &'static dyn ObImplAsync,
                                String,
                                Arc<Value>,
                            )
                                -> Pin<Box<dyn Future<Output = ()>>>,
                        >,
                    >,
                >,
            >,
        >,
    >,
}

impl ObImplAsync for Ob {
    #[must_use]
    #[allow(
        elided_named_lifetimes,
        clippy::type_complexity,
        clippy::type_repetition_in_bounds
    )]
    fn asyncfn<'life0, 'async_trait>(
        &'life0 self,
        path: String,
        value: Arc<Value>,
    ) -> ::core::pin::Pin<
        Box<
            dyn ::core::future::Future<Output = Option<Arc<Value>>>
                + ::core::marker::Send
                + 'async_trait,
        >,
    >
    where
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        todo!()
    }
}

impl Ob {
    fn fn_async<'life0>(
        &'static self,
        path: String,
        value: Arc<Value>,
    ) -> Pin<Box<dyn Future<Output = Option<Arc<Value>>> + Send>>
    where
        'life0: 'life0,
        Self: 'static,
    {
        let fn_async = self.fn_async.clone();
        let a = fn_async.as_ref().lock().unwrap();
        let b = a.as_ref().take().unwrap();
        let c = b.lock();
        let d = c.unwrap();
        let e = d.as_ref();
        let f = e(self, path, value); // error there
        Box::pin(async { None })
    }
}

I am trying to convert my sync code to async.
While the compiler helps by automagically transform dynamic sync function, it doesn't seem to be clever enough (for now) to manage dyn trait when switching to async.
The error is : cannot move out of *e which is behind a shared reference
move occurs because *e has type dyn std::ops::FnOnce(&dyn ObImplAsync, std::string::String, std::sync::Arc<Value>) -> std::pin::Pin<std::boxed::Box<dyn std::future::Future<Output = ()>>>, which does not implement the Copy trait

How can I do to convert the same sync function to async and be able to store it in my struct ?

Thank you in advance for your help.

I myself am not currently in a position to read through and inspect your code properly. But upon a brief look (of your code alone, before reading your error specifically), you'd want to use async versions of the sync traits.

If I recall, I will look at the code when I am in a better position to do so.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.