multithreading - 引用 Mutex 内部的数据
问题描述
我想访问受 RwLock 保护的数据。不幸的是,我被迫返回参考。
背景:我将rust-qt-binding-generator与 QtQuick 一起使用,我想可视化在 rust 端异步接收的数据。数据以 Vec 的形式出现,因此,我想在 Qt 端使用 QByteArray。rust-qt-binding-generator 提供了这种数据类型。
我的问题是生成的特征需要具有以下签名的 getter 函数:
fn channels(&self) -> &[u8]
代码:
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)]
use interface::*;
use std::sync::{Arc, RwLock, RwLockWriteGuard};
use std::time::Duration;
use std::thread;
pub struct RustController {
emit: RustControllerEmitter,
ch_vals: Vec<u8>,
channels: Arc<RwLock<Vec<u8>>>
}
impl RustControllerTrait for RustController {
fn new(emit: RustControllerEmitter) -> RustController {
let mut ret = RustController {
emit: emit.clone(),
ch_vals: vec!(),
channels: Arc::new(RwLock::new(create_empty_vector())),
};
update_thread(emit, ret.channels.clone());
ret
}
fn emit(&self) -> &RustControllerEmitter {
&self.emit
}
fn channels(&self) -> &[u8] {
// *((*self.channels).read().unwrap()).clone()
// does not work of course (and nothing else I tried obviously)
// because I can only get the value as a temporary one. writing
// them into self.ch_vals would solve the problem, but I am not
// allowed to get a &mut self
//&self.ch_vals // <-- this would work, but does not contain
// the values generated in the thread.
}
}
fn create_empty_vector() -> Vec<u8> {
let mut ret: Vec<u8> = Vec::with_capacity(512);
for i in 0..512 {
ret.push((i/2) as u8);
}
ret
}
fn update_thread(
emit: RustControllerEmitter,
channels: Arc<RwLock<Vec<u8>>>,
) {
thread::spawn(move || {
loop {
{
let mut w: RwLockWriteGuard<Vec<u8>> = (*channels).write().unwrap();
(*w)[0] += 1;
// changing values in the mutex is no problem, but no
// reference to the RustController here to store value
}
emit.channels_changed();
thread::sleep(Duration::from_secs(1));
}
});
}
如果你想自己运行它,这里是我的 bindings.json:
{
"cppFile": "src/Bindings.cpp",
"rust": {
"dir": "rust",
"interfaceModule": "interface",
"implementationModule": "implementation"
},
"objects": {
"RustController": {
"type": "Object",
"properties": {
"channels": {
"type": "QByteArray"
}
}
}
}
}
使用此设置,我可以毫无问题地传输 i32,但 Vec 由于吸气剂而无法工作。我对这个问题的理解是,我无法将额外线程中生成的值存储在可以在 getter 中引用的位置(并且寿命足够长,理想情况下只要使用 RustController)。
解决方案
推荐阅读
- javascript - CSS 变换旋转不在 Webkit / iPhone 上呈现(但适用于 Chrome Devtools 设备工具栏)
- go - 从 lint 问题报告中排除特定的文件集
- php - 如何在配置文件中使用 DB Facades?
- java - 从 Android 到我的 Django API 的 OAuth2 需要转到 /accounts/login
- karate - 功能“标签”过滤器在并行执行中无法正常工作
- python - Python:解码从网络上抓取的 unicode
- android - 如何从 Firebase 在 RecyclerView 中添加搜索过滤器
- spring - 我在下面的代码中使用@UniqueConstraint。当我使用 saveall() 方法时
- javascript - 如何让按钮在点击时显示
- c# - yield return 除了 IEnumerable 之外还有其他用途吗?