Estou escrevendo um sintetizador de áudio e quero usar a cpal
caixa para gerar áudio. Isso acontece gerando uma thread de saída, cuja função de "geração de dados" precisa implementar FnMut(&mut [T], &OutputCallbackInfo) + Send + 'static
. Isso OutputCallbackInfo
é irrelevante para a questão em questão.
Para gerar o áudio, tenho uma AudioPipeline
estrutura:
pub struct AudioPipeline {
producer: Box<dyn AudioProducer + Sync>,
modifiers: Vec<Box<dyn AudioModifier + Sync>>,
}
onde AudioProducer
e AudioModifier
são algumas outras características. Em main
, eu crio um pipeline e o envio para a thread gerada usando um fechamento móvel:
let pipeline = AudioPipeline::new(Box::new(sine), vec![Box::new(asdr)]);
let stream = device
.build_output_stream(
...
move |data: &mut [u8], callback_info: &cpal::OutputCallbackInfo| {
...
pipeline.recv();
...
},
...
);
Aqui pipeline.recv()
está um método AudioPipeline
que leva &mut self
.
O código não compila, retornando este erro:
(dyn AudioProducer + Sync + 'static) cannot be sent between threads safely
the trait bound Unique<(dyn AudioProducer + Sync + 'static)>: Send is not satisfied
required for Unique<(dyn AudioProducer + Sync + 'static)> to implement Send
Imagino que o problema tenha algo a ver com o uso de Box
? Mas acho esse erro um pouco difícil de entender: afinal, a documentação diz explicitamente "[ Unique<T>
] implementa Send
/ Sync
se T
for Send
/ Sync
." Certamente, ao exigir que o dyn AudioProducer
is também seja Sync
, ele definitivamente deveria ser Send
, certo? Provavelmente estou perdendo alguma sutileza de segurança de thread aqui.
Sync
não implicaSend
.Eles estão relacionados, mas não é como
Sync
se fossem um subtipoSend
ou algo assim. Existem tipos que sãoSend + !Sync
e outros que sãoSync + !Send
; cada um tem seu próprio significado.Portanto, seu objeto de característica precisa ser especificado
Send + Sync
- muito comum em código multithread.