// Async visitor variant: spawns a system thread, sends result as a message.
#[rustler::nif]
pub fn {{ func_name }}_with_visitor({{ with_params_str }}) -> Result<(), String> {
    let pid = env.pid();
    {{ with_deser }}

    let mut visitor_owned_env = rustler::OwnedEnv::new();
    let visitor_saved = visitor_owned_env.save({{ param_name }});
    {{ clone_stmts }}

    std::thread::spawn(move || {
        let bridge = {{ struct_name }}::new_from_saved(pid, visitor_owned_env, visitor_saved);
        let {{ param_name }}: Option<{{ handle_path }}> = Some(std::sync::Arc::new(std::sync::Mutex::new(bridge)) as {{ handle_path }});
        let mut result_env = rustler::OwnedEnv::new();
        let _ = result_env.send_and_clear(&pid, |env| {
            match {{ core_fn_path }}({{ with_call_args_str }}) {
                Ok(val) => {
                    let result: {{ return_type }} = val.into();
                    let ok_atom = rustler::types::atom::Atom::from_str(env, "ok").unwrap().to_term(env);
                    let result_term = result.encode(env);
                    rustler::types::tuple::make_tuple(env, &[ok_atom, result_term])
                },
                Err(e) => {
                    let err_atom = rustler::types::atom::Atom::from_str(env, "error").unwrap().to_term(env);
                    let reason = e.to_string().encode(env);
                    rustler::types::tuple::make_tuple(env, &[err_atom, reason])
                },
            }
        });
    });
    Ok(())
}
