tauri runtime Mutex/RwLock, type_hint
This commit is contained in:
parent
b32b6e4f87
commit
55f1b42ab0
|
@ -111,7 +111,9 @@ pub(super) async fn load_signal_and_get_timeline(
|
||||||
timeline_viewport_x,
|
timeline_viewport_x,
|
||||||
block_height,
|
block_height,
|
||||||
var_format,
|
var_format,
|
||||||
);
|
|value| Box::pin(async { value }),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
timeline
|
timeline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
use future::BoxFuture;
|
||||||
|
use wellen::SignalValue;
|
||||||
|
|
||||||
pub fn signal_to_timeline(
|
// @TODO remove once https://github.com/rust-lang/rust/issues/89976 is resolved
|
||||||
signal: &wellen::Signal,
|
// (`error: implementation of `FnOnce` is not general enough`)
|
||||||
|
fn type_hint<F>(f: F) -> F
|
||||||
|
where
|
||||||
|
F: for<'a> FnMut((u32, SignalValue<'a>)) -> (f64, SignalValue<'a>),
|
||||||
|
{
|
||||||
|
f
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn signal_to_timeline<'s>(
|
||||||
|
signal: &'s wellen::Signal,
|
||||||
time_table: &[wellen::Time],
|
time_table: &[wellen::Time],
|
||||||
timeline_zoom: f64,
|
timeline_zoom: f64,
|
||||||
timeline_viewport_width: u32,
|
timeline_viewport_width: u32,
|
||||||
timeline_viewport_x: i32,
|
timeline_viewport_x: i32,
|
||||||
block_height: u32,
|
block_height: u32,
|
||||||
var_format: VarFormat,
|
var_format: VarFormat,
|
||||||
|
mut format_by_decoders: impl FnMut(String) -> BoxFuture<'s, String>,
|
||||||
) -> Timeline {
|
) -> Timeline {
|
||||||
const MIN_BLOCK_WIDTH: u32 = 3;
|
const MIN_BLOCK_WIDTH: u32 = 3;
|
||||||
// Courier New, 16px, sync with `label_style` in `pixi_canvas.rs`
|
// Courier New, 16px, sync with `label_style` in `pixi_canvas.rs`
|
||||||
|
@ -25,12 +37,12 @@ pub fn signal_to_timeline(
|
||||||
|
|
||||||
let mut x_value_pairs = signal
|
let mut x_value_pairs = signal
|
||||||
.iter_changes()
|
.iter_changes()
|
||||||
.map(|(index, value)| {
|
.map(type_hint(move |(index, value)| {
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
let time = time_table[index] as f64;
|
let time = time_table[index] as f64;
|
||||||
let x = time / last_time * timeline_width - timeline_viewport_x;
|
let x = time / last_time * timeline_width - timeline_viewport_x;
|
||||||
(x, value)
|
(x, value)
|
||||||
})
|
}))
|
||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
// @TODO parallelize?
|
// @TODO parallelize?
|
||||||
|
@ -55,7 +67,8 @@ pub fn signal_to_timeline(
|
||||||
}
|
}
|
||||||
|
|
||||||
// @TODO cache?
|
// @TODO cache?
|
||||||
let value = var_format.format(value);
|
let mut value = var_format.format(value);
|
||||||
|
value = format_by_decoders(value).await;
|
||||||
|
|
||||||
let value_width = (value.chars().count() as f64 * LETTER_WIDTH) as u32;
|
let value_width = (value.chars().count() as f64 * LETTER_WIDTH) as u32;
|
||||||
// @TODO Ellipsis instead of hiding?
|
// @TODO Ellipsis instead of hiding?
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use crate::{AddedDecodersCount, DecoderPath, RemovedDecodersCount};
|
use crate::{AddedDecodersCount, DecoderPath, RemovedDecodersCount};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tauri::async_runtime::Mutex;
|
use tauri::async_runtime::{Mutex, RwLock};
|
||||||
use wasmtime::component::{Component as WasmtimeComponent, *};
|
use wasmtime::component::{Component as WasmtimeComponent, *};
|
||||||
use wasmtime::{AsContextMut, Engine, Store};
|
use wasmtime::{AsContextMut, Engine, Store};
|
||||||
use wasmtime_wasi::{WasiCtx, WasiView};
|
use wasmtime_wasi::{WasiCtx, WasiView};
|
||||||
|
|
||||||
bindgen!();
|
bindgen!();
|
||||||
|
|
||||||
static DECODERS: Lazy<Arc<Mutex<Vec<Component>>>> = Lazy::new(<_>::default);
|
pub static DECODERS: Lazy<Arc<RwLock<Vec<Component>>>> = Lazy::new(<_>::default);
|
||||||
static ENGINE: Lazy<Engine> = Lazy::new(<_>::default);
|
static ENGINE: Lazy<Engine> = Lazy::new(<_>::default);
|
||||||
static LINKER: Lazy<Linker<State>> = Lazy::new(|| {
|
static LINKER: Lazy<Linker<State>> = Lazy::new(|| {
|
||||||
let mut linker = Linker::new(&ENGINE);
|
let mut linker = Linker::new(&ENGINE);
|
||||||
|
@ -16,7 +16,7 @@ static LINKER: Lazy<Linker<State>> = Lazy::new(|| {
|
||||||
Component::add_to_linker(&mut linker, |state: &mut State| state).unwrap();
|
Component::add_to_linker(&mut linker, |state: &mut State| state).unwrap();
|
||||||
linker
|
linker
|
||||||
});
|
});
|
||||||
static STORE: Lazy<Arc<Mutex<Store<State>>>> = Lazy::new(|| {
|
pub static STORE: Lazy<Arc<Mutex<Store<State>>>> = Lazy::new(|| {
|
||||||
let store = Store::new(
|
let store = Store::new(
|
||||||
&ENGINE,
|
&ENGINE,
|
||||||
State {
|
State {
|
||||||
|
@ -27,7 +27,7 @@ static STORE: Lazy<Arc<Mutex<Store<State>>>> = Lazy::new(|| {
|
||||||
Arc::new(Mutex::new(store))
|
Arc::new(Mutex::new(store))
|
||||||
});
|
});
|
||||||
|
|
||||||
struct State {
|
pub struct State {
|
||||||
ctx: WasiCtx,
|
ctx: WasiCtx,
|
||||||
table: ResourceTable,
|
table: ResourceTable,
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ impl component::decoder::host::Host for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn remove_all_decoders() -> RemovedDecodersCount {
|
pub async fn remove_all_decoders() -> RemovedDecodersCount {
|
||||||
let mut decoders = DECODERS.lock().await;
|
let mut decoders = DECODERS.write().await;
|
||||||
let decoders_count = decoders.len();
|
let decoders_count = decoders.len();
|
||||||
decoders.clear();
|
decoders.clear();
|
||||||
decoders_count
|
decoders_count
|
||||||
|
@ -98,7 +98,7 @@ async fn add_decoder(path: &str) -> wasmtime::Result<()> {
|
||||||
.component_decoder_decoder()
|
.component_decoder_decoder()
|
||||||
.call_init(&mut store)?;
|
.call_init(&mut store)?;
|
||||||
|
|
||||||
DECODERS.lock().await.push(component);
|
DECODERS.write().await.push(component);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::Mutex;
|
use tauri::async_runtime::RwLock;
|
||||||
use tauri_plugin_dialog::DialogExt;
|
use tauri_plugin_dialog::DialogExt;
|
||||||
|
use wasmtime::AsContextMut;
|
||||||
use wellen::simple::Waveform;
|
use wellen::simple::Waveform;
|
||||||
|
|
||||||
type Filename = String;
|
type Filename = String;
|
||||||
|
@ -13,7 +14,7 @@ mod component_manager;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Store {
|
struct Store {
|
||||||
waveform: Mutex<Option<Waveform>>,
|
waveform: RwLock<Option<Waveform>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command(rename_all = "snake_case")]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
|
@ -35,7 +36,7 @@ async fn pick_and_load_waveform(
|
||||||
let Ok(waveform) = waveform else {
|
let Ok(waveform) = waveform else {
|
||||||
panic!("Waveform file reading failed")
|
panic!("Waveform file reading failed")
|
||||||
};
|
};
|
||||||
*store.waveform.lock().unwrap() = Some(waveform);
|
*store.waveform.write().await = Some(waveform);
|
||||||
Ok(Some(file_response.name.unwrap()))
|
Ok(Some(file_response.name.unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +54,9 @@ async fn load_file_with_selected_vars(app: tauri::AppHandle) -> Result<Option<Ja
|
||||||
|
|
||||||
#[tauri::command(rename_all = "snake_case")]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn get_hierarchy(store: tauri::State<'_, Store>) -> Result<serde_json::Value, ()> {
|
async fn get_hierarchy(store: tauri::State<'_, Store>) -> Result<serde_json::Value, ()> {
|
||||||
let waveform = store.waveform.lock().unwrap();
|
let waveform_lock = store.waveform.read().await;
|
||||||
let hierarchy = waveform.as_ref().unwrap().hierarchy();
|
let waveform = waveform_lock.as_ref().unwrap();
|
||||||
|
let hierarchy = waveform.hierarchy();
|
||||||
Ok(serde_json::to_value(hierarchy).unwrap())
|
Ok(serde_json::to_value(hierarchy).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +72,7 @@ async fn load_signal_and_get_timeline(
|
||||||
) -> Result<serde_json::Value, ()> {
|
) -> Result<serde_json::Value, ()> {
|
||||||
// @TODO run (all?) in a blocking thread?
|
// @TODO run (all?) in a blocking thread?
|
||||||
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap();
|
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap();
|
||||||
let mut waveform_lock = store.waveform.lock().unwrap();
|
let mut waveform_lock = store.waveform.write().await;
|
||||||
let waveform = waveform_lock.as_mut().unwrap();
|
let waveform = waveform_lock.as_mut().unwrap();
|
||||||
waveform.load_signals_multi_threaded(&[signal_ref]);
|
waveform.load_signals_multi_threaded(&[signal_ref]);
|
||||||
let signal = waveform.get_signal(signal_ref).unwrap();
|
let signal = waveform.get_signal(signal_ref).unwrap();
|
||||||
|
@ -83,14 +85,29 @@ async fn load_signal_and_get_timeline(
|
||||||
timeline_viewport_x,
|
timeline_viewport_x,
|
||||||
block_height,
|
block_height,
|
||||||
var_format,
|
var_format,
|
||||||
);
|
|mut value: String| {
|
||||||
|
Box::pin(async {
|
||||||
|
let decoders = component_manager::DECODERS.read().await;
|
||||||
|
let mut store_lock = component_manager::STORE.lock().await;
|
||||||
|
let mut store = store_lock.as_context_mut();
|
||||||
|
for decoder in decoders.iter() {
|
||||||
|
value = decoder
|
||||||
|
.component_decoder_decoder()
|
||||||
|
.call_format_signal_value(&mut store, &value)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
value
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
Ok(serde_json::to_value(timeline).unwrap())
|
Ok(serde_json::to_value(timeline).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command(rename_all = "snake_case")]
|
#[tauri::command(rename_all = "snake_case")]
|
||||||
async fn unload_signal(signal_ref_index: usize, store: tauri::State<'_, Store>) -> Result<(), ()> {
|
async fn unload_signal(signal_ref_index: usize, store: tauri::State<'_, Store>) -> Result<(), ()> {
|
||||||
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap();
|
let signal_ref = wellen::SignalRef::from_index(signal_ref_index).unwrap();
|
||||||
let mut waveform_lock = store.waveform.lock().unwrap();
|
let mut waveform_lock = store.waveform.write().await;
|
||||||
let waveform = waveform_lock.as_mut().unwrap();
|
let waveform = waveform_lock.as_mut().unwrap();
|
||||||
waveform.unload_signals(&[signal_ref]);
|
waveform.unload_signals(&[signal_ref]);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue