use tokio mutex (#1112)

* use tokio mutex

* more
This commit is contained in:
Logan McNaughton
2026-06-23 12:27:15 +02:00
committed by GitHub
parent 119e9044a8
commit dee2b85daa
4 changed files with 62 additions and 106 deletions
+1 -1
View File
@@ -349,7 +349,7 @@ impl Device {
load_state: false,
load_rewind: false,
last_rewind_saved: 0.0,
rewind_pool: std::sync::Arc::new(std::sync::Mutex::new(
rewind_pool: std::sync::Arc::new(tokio::sync::Mutex::new(
std::collections::BTreeMap::new(),
)),
},
+7 -9
View File
@@ -105,7 +105,7 @@ fn set_app_id() {
}
pub fn create_runtime() -> (tokio::sync::oneshot::Sender<()>, tokio::runtime::Handle) {
let (tx, rx) = std::sync::mpsc::channel();
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
let (close_tx, close_rx) = tokio::sync::oneshot::channel::<()>();
std::thread::spawn(move || {
@@ -114,7 +114,7 @@ pub fn create_runtime() -> (tokio::sync::oneshot::Sender<()>, tokio::runtime::Ha
rt.block_on(close_rx).unwrap();
});
(close_tx, rx.recv().unwrap())
(close_tx, rx.blocking_recv().unwrap())
}
pub fn run(args: Args, arg_count: usize) -> std::io::Result<()> {
@@ -352,9 +352,7 @@ fn android_main(app: slint::android::AndroidApp) {
slint::android::init_with_event_listener(app.clone(), move |event| match event {
slint::android::android_activity::PollEvent::Main(main_event) => match main_event {
slint::android::android_activity::MainEvent::TerminateWindow { .. } => {
if let Ok(weak_app_window) = android::WEAK_SLINT_WINDOW.lock()
&& let Some(weak_app_window) = weak_app_window.as_ref()
{
if let Some(weak_app_window) = android::WEAK_SLINT_WINDOW.blocking_lock().as_ref() {
weak_app_window
.upgrade_in_event_loop(move |handle| {
ui::gui::save_settings(&handle);
@@ -369,9 +367,9 @@ fn android_main(app: slint::android::AndroidApp) {
})
.unwrap();
let app_window = ui::gui::AppWindow::new().unwrap();
*android::WEAK_SLINT_WINDOW.lock().unwrap() = Some(app_window.as_weak());
*android::WEAK_SLINT_WINDOW.blocking_lock() = Some(app_window.as_weak());
*android::ANDROID_APP.lock().unwrap() = Some(app);
*android::ANDROID_APP.blocking_lock() = Some(app);
let dirs = ui::get_dirs();
@@ -382,6 +380,6 @@ fn android_main(app: slint::android::AndroidApp) {
ui::gui::app_window(&app_window, true);
close_tx.send(()).unwrap();
*android::WEAK_SLINT_WINDOW.lock().unwrap() = None;
*android::ANDROID_APP.lock().unwrap() = None;
*android::WEAK_SLINT_WINDOW.blocking_lock() = None;
*android::ANDROID_APP.blocking_lock() = None;
}
+35 -52
View File
@@ -78,7 +78,7 @@ pub struct Savestate {
pub last_rewind_saved: f64,
#[serde(skip)]
pub rewind_pool:
std::sync::Arc<std::sync::Mutex<std::collections::BTreeMap<i32, SavestateData>>>,
std::sync::Arc<tokio::sync::Mutex<std::collections::BTreeMap<i32, SavestateData>>>,
}
pub struct SavestateData {
@@ -88,11 +88,11 @@ pub struct SavestateData {
ra_state: Vec<u8>,
}
static DEVICE_CLONE: std::sync::LazyLock<std::sync::Mutex<Box<device::Device>>> =
std::sync::LazyLock::new(|| std::sync::Mutex::new(device::Device::new(false)));
static DEVICE_CLONE: std::sync::LazyLock<tokio::sync::Mutex<Box<device::Device>>> =
std::sync::LazyLock::new(|| tokio::sync::Mutex::new(device::Device::new(false)));
static SAVES_CLONE: std::sync::LazyLock<std::sync::Mutex<ui::storage::Saves>> =
std::sync::LazyLock::new(|| std::sync::Mutex::new(ui::storage::Saves::default()));
static SAVES_CLONE: std::sync::LazyLock<tokio::sync::Mutex<ui::storage::Saves>> =
std::sync::LazyLock::new(|| tokio::sync::Mutex::new(ui::storage::Saves::default()));
pub fn process_savestates(device: &mut device::Device) {
let save_rewind = if device.netplay.is_none()
@@ -126,18 +126,10 @@ pub fn create_savestate(device: &mut device::Device, rewind: bool, rewind_frame:
let mut ra_state: Vec<u8> = vec![0; retroachievements::state_size()];
retroachievements::save_state(ra_state.as_mut_ptr(), ra_state.len());
if let Ok(mut device_clone) = DEVICE_CLONE.lock()
&& let Ok(mut saves_clone) = SAVES_CLONE.lock()
{
device_clone.clone_state(device);
saves_clone.clone_from(&device.ui.storage.saves);
} else {
ui::video::onscreen_message(
"Failed to create savestate",
ui::video::MESSAGE_LENGTH_MESSAGE_SHORT,
);
return;
}
DEVICE_CLONE.blocking_lock().clone_state(device);
SAVES_CLONE
.blocking_lock()
.clone_from(&device.ui.storage.saves);
let save_path = device.ui.storage.paths.savestate_file_path.clone();
let save_state_slot = device.ui.storage.save_state_slot;
@@ -147,39 +139,32 @@ pub fn create_savestate(device: &mut device::Device, rewind: bool, rewind_frame:
let mut error = false;
if rewind {
if let Ok(device_clone) = DEVICE_CLONE.lock()
&& let Ok(saves_clone) = SAVES_CLONE.lock()
&& let Ok(mut pool) = rewind_pool.lock()
{
let mut state = device::Device::new(false);
state.clone_state(device_clone.deref());
let key = if let Some(key) = rewind_frame {
key
} else if let Some(key) = pool.keys().last() {
key + 1
} else {
0
};
pool.insert(
key,
SavestateData {
device: state,
saves: saves_clone.clone(),
rdp_state,
ra_state,
},
);
if pool.len() > 30 {
pool.pop_first();
}
let mut pool = rewind_pool.lock().await;
let mut state = device::Device::new(false);
state.clone_state(DEVICE_CLONE.lock().await.deref());
let key = if let Some(key) = rewind_frame {
key
} else if let Some(key) = pool.keys().last() {
key + 1
} else {
error = true;
0
};
pool.insert(
key,
SavestateData {
device: state,
saves: SAVES_CLONE.lock().await.clone(),
rdp_state,
ra_state,
},
);
if pool.len() > 30 {
pool.pop_first();
}
} else {
let compressed_file = if let Ok(device_clone) = DEVICE_CLONE.lock()
&& let Ok(saves_clone) = SAVES_CLONE.lock()
&& let Ok(device_data) = postcard::to_stdvec(device_clone.deref())
&& let Ok(saves_data) = postcard::to_stdvec(saves_clone.deref())
let compressed_file = if let Ok(device_data) =
postcard::to_stdvec(DEVICE_CLONE.lock().await.deref())
&& let Ok(saves_data) = postcard::to_stdvec(SAVES_CLONE.lock().await.deref())
&& let Ok(compressed_file) = ui::storage::compress_file(&[
(&device_data, "device"),
(&saves_data, "saves"),
@@ -229,17 +214,15 @@ pub fn load_savestate(device: &mut device::Device, rewind: bool, rewind_frame: O
let timeout = std::time::Duration::from_secs(1);
let now = std::time::Instant::now();
loop {
if let Ok(mut pool) = device.savestate.rewind_pool.lock()
&& pool.contains_key(&rewind_frame)
{
let mut pool = device.savestate.rewind_pool.blocking_lock();
if pool.contains_key(&rewind_frame) {
break pool.remove(&rewind_frame);
}
if now.elapsed() > timeout {
break None;
}
}
} else if let Ok(mut pool) = device.savestate.rewind_pool.lock()
&& let Some((_key, state)) = pool.pop_last()
} else if let Some((_key, state)) = device.savestate.rewind_pool.blocking_lock().pop_last()
{
Some(state)
} else {
+19 -44
View File
@@ -13,15 +13,15 @@ const REQUEST_SELECT_ROM: jint = 1;
const CONFIGURE_INPUT_PROFILE: jint = 2;
const RUN_ROM: jint = 3;
pub static ANDROID_APP: std::sync::Mutex<Option<slint::android::AndroidApp>> =
std::sync::Mutex::new(None);
pub static ANDROID_APP: tokio::sync::Mutex<Option<slint::android::AndroidApp>> =
tokio::sync::Mutex::const_new(None);
pub static SELECT_ROM_TX: std::sync::Mutex<
pub static SELECT_ROM_TX: tokio::sync::Mutex<
Option<tokio::sync::oneshot::Sender<Option<std::path::PathBuf>>>,
> = std::sync::Mutex::new(None);
> = tokio::sync::Mutex::const_new(None);
pub static WEAK_SLINT_WINDOW: std::sync::Mutex<Option<slint::Weak<ui::gui::AppWindow>>> =
std::sync::Mutex::new(None);
pub static WEAK_SLINT_WINDOW: tokio::sync::Mutex<Option<slint::Weak<ui::gui::AppWindow>>> =
tokio::sync::Mutex::const_new(None);
bind_java_type! {
DocumentsContract => "android.provider.DocumentsContract",
@@ -197,9 +197,7 @@ fn start_configure_input_profile_on_jvm(
dinput: bool,
deadzone: i32,
) -> jni::errors::Result<()> {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe { env.as_cast_raw::<Global<AndroidActivity>>(&raw_activity_global)? };
@@ -256,9 +254,7 @@ fn start_run_rom_on_jvm(
netplay: Option<ui::gui::NetplayDevice>,
weak: slint::Weak<ui::gui::AppWindow>,
) -> jni::errors::Result<()> {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe { env.as_cast_raw::<Global<AndroidActivity>>(&raw_activity_global)? };
@@ -330,9 +326,7 @@ fn start_run_rom_on_jvm(
}
fn get_vm() -> Option<JavaVM> {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
Some(unsafe { JavaVM::from_raw(app.vm_as_ptr().cast()) })
} else {
None
@@ -431,9 +425,7 @@ pub fn open_uri(path: &str) {
}
fn open_uri_on_jvm(env: &mut Env<'_>, path: &str) -> jni::errors::Result<()> {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe { env.as_cast_raw::<Global<AndroidActivity>>(&raw_activity_global)? };
@@ -459,12 +451,8 @@ pub async fn select_rom(rom_dir: slint::SharedString) -> Option<std::path::PathB
return None;
}
let (tx, rx) = tokio::sync::oneshot::channel::<Option<std::path::PathBuf>>();
if let Ok(mut tx_lock) = SELECT_ROM_TX.lock() {
tx_lock.replace(tx);
} else {
eprintln!("Error locking SELECT_ROM_TX");
return None;
}
SELECT_ROM_TX.lock().await.replace(tx);
rx.await.unwrap_or(None)
} else {
eprintln!("Android app not initialized");
@@ -481,9 +469,7 @@ pub async fn select_gb_ram(_player: i32) -> Option<std::path::PathBuf> {
}
fn select_rom_on_jvm(env: &mut Env<'_>, rom_dir: String) -> jni::errors::Result<()> {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe { env.as_cast_raw::<Global<AndroidActivity>>(&raw_activity_global)? };
@@ -507,9 +493,7 @@ fn select_rom_on_jvm(env: &mut Env<'_>, rom_dir: String) -> jni::errors::Result<
}
pub fn get_dirs() -> ui::Dirs {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
ui::Dirs {
config_dir: app.internal_data_path().unwrap().join("config"),
data_dir: app.external_data_path().unwrap().join("data"),
@@ -559,9 +543,7 @@ fn get_file_from_uri_on_jvm(
env: &mut Env<'_>,
path: String,
) -> jni::errors::Result<Option<std::fs::File>> {
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe { env.as_cast_raw::<Global<AndroidActivity>>(&raw_activity_global)? };
let path = JString::from_str(env, path)?;
@@ -600,8 +582,7 @@ pub extern "system" fn Java_io_github_gopher64_gopher64_SlintActivity_nativeOnAc
if result_code == AndroidActivity::RESULT_OK(env)? {
match request_code {
REQUEST_SELECT_ROM => {
if let Ok(mut tx_lock) = SELECT_ROM_TX.lock()
&& let Some(tx) = tx_lock.take()
if let Some(tx) = SELECT_ROM_TX.blocking_lock().take()
&& !intent_data.is_null()
{
let result_intent =
@@ -612,9 +593,7 @@ pub extern "system" fn Java_io_github_gopher64_gopher64_SlintActivity_nativeOnAc
return Ok(());
}
if let Ok(app) = ANDROID_APP.lock()
&& let Some(app) = app.as_ref()
{
if let Some(app) = ANDROID_APP.blocking_lock().as_ref() {
let raw_activity_global = app.activity_as_ptr() as jni::sys::jobject;
let activity = unsafe {
env.as_cast_raw::<Global<AndroidActivity>>(&raw_activity_global)?
@@ -635,9 +614,7 @@ pub extern "system" fn Java_io_github_gopher64_gopher64_SlintActivity_nativeOnAc
}
}
CONFIGURE_INPUT_PROFILE => {
if let Ok(weak_app_window) = WEAK_SLINT_WINDOW.lock()
&& let Some(weak_app_window) = weak_app_window.as_ref()
{
if let Some(weak_app_window) = WEAK_SLINT_WINDOW.blocking_lock().as_ref() {
let config = ui::config::Config::new();
ui::gui::update_input_profiles(&weak_app_window, &config);
}
@@ -659,9 +636,7 @@ pub extern "system" fn Java_io_github_gopher64_gopher64_SlintActivity_nativeOnAc
{
let _ = std::fs::remove_file(cheats_path);
}
if let Ok(weak_app_window) = WEAK_SLINT_WINDOW.lock()
&& let Some(weak_app_window) = weak_app_window.as_ref()
{
if let Some(weak_app_window) = WEAK_SLINT_WINDOW.blocking_lock().as_ref() {
weak_app_window
.upgrade_in_event_loop(move |handle| {
ui::gui::update_recent_roms(&handle, file_path.into());