The main thread no longers locks the game file's cdrom.

This commit is contained in:
Filipe Rodrigues 2021-06-05 16:10:51 +01:00
parent e080bf3c4c
commit 17e352ba51
3 changed files with 46 additions and 21 deletions

View File

@ -8,7 +8,11 @@ use anyhow::Context;
use dcb_cdrom_xa::CdRomCursor;
use dcb_util::MutexPoison;
use eframe::egui;
use std::{fs, sync::Mutex};
use std::{
fs,
io::{self, Write},
sync::Mutex,
};
/// Game file
pub struct GameFile {
@ -20,7 +24,7 @@ pub struct GameFile {
}
impl GameFile {
/// Creates a new game
/// Creates a new game file from it's file
pub fn new(file: fs::File) -> Result<Self, anyhow::Error> {
let mut cdrom = CdRomCursor::new(file);
let mut game_file = dcb_io::GameFile::new(&mut cdrom);
@ -94,6 +98,11 @@ impl GameFile {
Ok(())
}
/// Flushes the game file to disc
pub fn flush(&self) -> Result<(), io::Error> {
self.cdrom.lock_unwrap().flush()
}
/// Displays the game file tree
pub fn display(
&self, ui: &mut egui::Ui, file_search: &mut String, swap_window: &mut Option<SwapWindow>,
@ -126,7 +135,14 @@ impl GameFile {
/// Performs an operation using the game file
pub fn with_game_file<T>(&self, f: impl FnOnce(dcb_io::GameFile<&mut CdRomCursor<fs::File>>) -> T) -> T {
// TODO: Check if main thread is using the game file, as it shouldn't be
// We shouldn't be called from the main thread, as locking might
// TODO: Get a better way of making sure it's the main thread and not some
// other thread with the name 'main'?
debug_assert_ne!(
std::thread::current().name(),
Some("main"),
"Main thread should not call this function, as it might block for an indeterminate amount of time"
);
// Get the game file
let mut cdrom = self.cdrom.lock_unwrap();

View File

@ -25,7 +25,7 @@ use eframe::{egui, epi, NativeOptions};
use game_file::GameFile;
use native_dialog::FileDialog;
use preview_panel::{PreviewPanel, PreviewPanelBuilder};
use std::{fs, io::Write, path::PathBuf, sync::Arc};
use std::{fs, path::PathBuf, sync::Arc};
use swap_window::SwapWindow;
fn main() {
@ -192,10 +192,10 @@ impl epi::App for FileEditor {
// Flush the file if we have it
if let Some(game_file) = &mut self.game_file {
game_file.with_game_file(|mut game| match game.cdrom().flush() {
match game_file.flush() {
Ok(()) => (),
Err(err) => alert::error(&format!("Unable to flush file tod isk: {:?}", err)),
})
}
}
}

View File

@ -4,9 +4,9 @@
use crate::GameFile;
use anyhow::Context;
use dcb_io::game_file::Path;
use dcb_util::alert;
use dcb_util::{alert, task};
use eframe::egui;
use std::mem;
use std::{mem, sync::Arc};
/// Swap window
#[derive(PartialEq, Clone, Default)]
@ -30,7 +30,7 @@ impl SwapWindow {
}
/// Displays this swap window
pub fn display(&mut self, ctx: &egui::CtxRef, game_file: &GameFile) {
pub fn display(&mut self, ctx: &egui::CtxRef, game_file: &Arc<GameFile>) {
egui::Window::new("Swap screen").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label(self.first.as_str().unwrap_or("None"));
@ -47,21 +47,30 @@ impl SwapWindow {
if ui.button("Swap").clicked() {
match (&self.first, &self.second) {
// If we got both, spawn the task to swap the files
(SwapFileStatus::Set(lhs), SwapFileStatus::Set(rhs)) => {
let lhs = Path::from_ascii(lhs).expect("Lhs path wasn't valid");
let rhs = Path::from_ascii(rhs).expect("Rhs path wasn't valid");
let lhs = lhs.clone();
let rhs = rhs.clone();
let game_file = Arc::clone(game_file);
task::spawn(move || {
// TODO: Use `PathBuf` once `dcb_io` supports it
let lhs = Path::from_ascii(&lhs).expect("Lhs path wasn't valid");
let rhs = Path::from_ascii(&rhs).expect("Rhs path wasn't valid");
let res: Result<_, anyhow::Error> = try {
game_file.with_game_file(|mut game_file| {
game_file.swap_files(lhs, rhs).context("Unable to swap files")
})?;
game_file.reload().context("Unable to reload the game")?;
};
// Try to swap them and reload the game file
let res: Result<_, anyhow::Error> = try {
game_file.with_game_file(|mut game_file| {
game_file.swap_files(lhs, rhs).context("Unable to swap files")
})?;
game_file.reload().context("Unable to reload the game")?;
};
match res {
Ok(()) => alert::info("Successfully swapped!"),
Err(err) => alert::error(&format!("Unable to swap files: {:?}", err)),
}
// Then alert the user
match res {
Ok(()) => alert::info("Successfully swapped {lhs} with {rhs}!"),
Err(err) => alert::error(&format!("Unable to swap files: {:?}", err)),
}
});
},
_ => alert::warn("You must set both files before swapping"),
}