Closed lifeRobot closed 6 months ago
I'm not sure what your code is doing because i'm not familiar with cbsk. But i'm afraid that there might be something wrong with threading and this MutDataObj. VecModel
I'm not sure what your code is doing because i'm not familiar with cbsk. But i'm afraid that there might be something wrong with threading and this MutDataObj. VecModel is not Sync, and Rc is not Send, so there shouldn't be accessible from different thread at the same time, but it seems that your code does that.
self.array.borrow_mut()
and self.array.borrow()
are called, self.array.borrow_mut() will set borrow
to -1, adding locks to multiple threads can solve this problemI can trivially reproduce the bug without using Slint by simply using a RefCell:
use std::rc::Rc;
use std::time::Duration;
use cbsk_base::once_cell::sync::Lazy;
use cbsk_base::tokio;
use cbsk_base::tokio::task::JoinHandle;
use cbsk_mut_data::mut_data_obj::MutDataObj;
use std::cell::RefCell;
static A: Lazy<MutDataObj<Rc<RefCell<i32>>>> = Lazy::new(MutDataObj::default);
#[tokio::main]
pub async fn main() {
let h = vec![set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data()];
for h in h {
h.await.unwrap()
}
}
fn set_row_data() -> JoinHandle<()> {
tokio::spawn(async {
loop {
let count = *A.borrow();
println!("count is {count}");
*A.borrow_mut() += 1;
tokio::time::sleep(Duration::from_millis(100)).await;
}
})
}
I think that MutDataObj
is unsound.
(the output is something like)
count is 0
count is 0
count is 0
thread 'tokio-runtime-workercount is 2
' panicked at src/main.rscount is 1
:28:16:
already borrowed: BorrowMutError
count is 1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
count is 1
count is 1
count is 3
count is 4
count is 9
count is 10
count is 11
count is 12
count is 12
thread 'tokio-runtime-worker' panicked at src/main.rs:28:16:
already borrowed: BorrowMutError
thread 'main' panicked at src/main.rs:19:17:
I'm going to close this since this is not a Slint bug.
version
slint 1.5.0 rust 1.76.0
example code
code
Cargo.toml: ``` [dependencies] slint = "1.5.0" cbsk_base = { version = "0.1.7", features = ["once_cell", "tokio_full"] } cbsk_mut_data = { version = "0.1.4", default-features = false, features = ["obj"] } ``` main.rs : ``` use std::rc::Rc; use std::time::Duration; use cbsk_base::once_cell::sync::Lazy; use cbsk_base::tokio; use cbsk_base::tokio::task::JoinHandle; use cbsk_mut_data::mut_data_obj::MutDataObj; use slint::{Model, VecModel}; static A: Lazy>>> = Lazy::new(MutDataObj::default);
#[tokio::main]
pub async fn main() {
let h = vec![set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data(), set_row_data()];
for h in h {
h.await.unwrap()
}
}
fn set_row_data() -> JoinHandle<()> {
tokio::spawn(async {
loop {
let count = A.row_count();
println!("count is {count}");
A.set_row_data(3, 0);
tokio::time::sleep(Duration::from_millis(100)).await;
}
})
}
```
error msg
analysis
self.array.borrow().len()
from slint-core::model.rs in line 395self.array.borrow().len()
used the following code internally:code
fn is_reading is:
borrow.get().wrapping_add(1) < 0
, this is a logical problem with reference counting, so, this may not be is slint problem, but is rust problemopinion
I suggest changing
self.array.borrow()
toself.array.try_borrow()
, or use third-party internal variability code, such as dark-std or cbsk_mut_data