Rust 成员在实时安全代码中充当多线程可变回调

Rust member functions as multithreaded mutable callbacks in real-time safe code

提问人:WalleyM 提问时间:1/8/2023 最后编辑:WalleyM 更新时间:1/8/2023 访问量:69

问:

我希望使用结构的成员函数作为可变回调。我这样做的标准方法是将我的结构实例包装在互斥锁中,然后包装在 Arc 中。但是,在此用例中,我的回调是实时音频回调,它需要实时安全,并在专用线程上触发。这意味着不会发生任何可能延迟回调发生的锁定。

我的实际成员回调方法必须对结构进行可变引用(我认为这就是事情分崩离析的地方)。结构体确实包含成员,但这些成员都可以是原子变量。

这是我正在寻找的那种东西的一个例子:

use std::sync::Arc;
use clap::error;
use cpal::{traits::{HostTrait, DeviceTrait}, StreamConfig, OutputCallbackInfo, StreamError};
use std::sync::atomic::AtomicI16;

pub struct AudioProcessor {
     var: AtomicI16,
}

impl AudioProcessor {
    fn audio_block_f32(&mut self, audio: &mut [f32], _info: &OutputCallbackInfo) {
    }

    fn audio_error(&mut self, error: StreamError) {
    }
}

fn initAudio()
{
     let out_dev = cpal::default_host().default_output_device().expect("No available output device found");

     let mut supported_configs_range = out_dev.supported_output_configs().expect("Could not obtain device configs");
     let config = supported_configs_range.next().expect("No available configs").with_max_sample_rate();

     let proc = Arc::new(AudioProcessor{var: AtomicI16::new(5)});
     let audio_callback_instance = proc.clone();
     let error_callback_instance = proc.clone();

     out_dev.build_output_stream(&StreamConfig::from(config), move |audio: &mut [f32], info: &OutputCallbackInfo| audio_callback_instance.audio_block_f32(audio, info), move |stream_error| error_callback_instance.clone().audio_error(stream_error));
 }

目前,此代码在 build_output_stream() 函数中失败,并显示以下错误消息:

无法借用 AS 可变数据 trait 需要通过取消引用进行修改,但不会为ArcDerefMutArc<AudioProcessor>

有没有处理此类问题的标准方法?

多线程 音频 Rust 回调

评论

0赞 Ivan C 1/8/2023
我这样做的方式是,我让音频制作人线程通过通道将样本发送到处理音频设备的线程。
0赞 cafce25 1/8/2023
您应该提供一个最小的可重现示例,包括“此代码如何失败”(编译器输出、执行与实际行为等)。
0赞 WalleyM 1/8/2023
@IvanC你能解释一下吗?您使用哪种技术来发送样品?它仍然实时安全吗?
0赞 WalleyM 1/8/2023
@cafce25该示例是一个最小的可重现示例。我现在已经添加了错误消息。
1赞 Chayim Friedman 1/8/2023
如果所有字段都是原子的,为什么需要可变引用?

答: 暂无答案