EpisodeWidget: Replace some Mutexs with RefCells.

The state machines are not send and the code is sequnecial.
We only need `&mut machine` refference to pass to `take_mut::take`
to change the state of the machine. In 2/3 cases we can even use
`.get_mut()` method and even avoid the dynamic borrow checks at
runtime. For the `TitleMachine` The only thing that will hold
a refference to it after initialization will be the play_button
callback. So it's justifiable to use `RefCell` insetead of a `Mutex`.
This commit is contained in:
Jordan Petridis 2018-03-13 04:44:06 +02:00
parent 74712b5410
commit fc9579cd51
No known key found for this signature in database
GPG Key ID: CEABAD9F5683B9A6

View File

@ -15,6 +15,7 @@ use app::Action;
use manager; use manager;
use widgets::episode_states::*; use widgets::episode_states::*;
use std::cell::RefCell;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::path::Path; use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
@ -24,9 +25,9 @@ use std::sync::mpsc::Sender;
#[derive(Debug)] #[derive(Debug)]
pub struct EpisodeWidget { pub struct EpisodeWidget {
pub container: gtk::Box, pub container: gtk::Box,
date: Mutex<DateMachine>, date: RefCell<DateMachine>,
duration: Mutex<DurationMachine>, duration: RefCell<DurationMachine>,
title: Rc<Mutex<TitleMachine>>, title: Rc<RefCell<TitleMachine>>,
media: Arc<Mutex<MediaMachine>>, media: Arc<Mutex<MediaMachine>>,
} }
@ -51,9 +52,9 @@ impl Default for EpisodeWidget {
let separator2: gtk::Label = builder.get_object("separator2").unwrap(); let separator2: gtk::Label = builder.get_object("separator2").unwrap();
let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap(); let prog_separator: gtk::Label = builder.get_object("prog_separator").unwrap();
let date_machine = Mutex::new(DateMachine::new(date, 0)); let date_machine = RefCell::new(DateMachine::new(date, 0));
let dur_machine = Mutex::new(DurationMachine::new(duration, separator1, None)); let dur_machine = RefCell::new(DurationMachine::new(duration, separator1, None));
let title_machine = Rc::new(Mutex::new(TitleMachine::new(title, false))); let title_machine = Rc::new(RefCell::new(TitleMachine::new(title, false)));
let media = MediaMachine::new( let media = MediaMachine::new(
play, play,
download, download,
@ -87,19 +88,13 @@ impl EpisodeWidget {
WidgetExt::set_name(&self.container, &episode.rowid().to_string()); WidgetExt::set_name(&self.container, &episode.rowid().to_string());
// Set the date label. // Set the date label.
if let Err(err) = self.set_date(episode.epoch()) { self.set_date(episode.epoch());
error!("Failed to determine date state: {}", err);
}
// Set the title label state. // Set the title label state.
if let Err(err) = self.set_title(&episode) { self.set_title(&episode);
error!("Failed to determine title state: {}", err);
}
// Set the duaration label. // Set the duaration label.
if let Err(err) = self.set_duration(episode.duration()) { self.set_duration(episode.duration());
error!("Failed to set duration state: {}", err);
}
// Determine what the state of the media widgets should be. // Determine what the state of the media widgets should be.
if let Err(err) = self.determine_media_state(&episode) { if let Err(err) = self.determine_media_state(&episode) {
@ -137,31 +132,24 @@ impl EpisodeWidget {
} }
/// Determine the title state. /// Determine the title state.
fn set_title(&mut self, episode: &EpisodeWidgetQuery) -> Result<(), Error> { fn set_title(&mut self, episode: &EpisodeWidgetQuery) {
let mut lock = self.title.lock().map_err(|err| format_err!("{}", err))?; let mut machine = self.title.borrow_mut();
lock.set_title(episode.title()); machine.set_title(episode.title());
take_mut::take(lock.deref_mut(), |title| { take_mut::take(machine.deref_mut(), |title| {
title.determine_state(episode.played().is_some()) title.determine_state(episode.played().is_some())
}); });
Ok(())
} }
/// Set the date label depending on the current time. /// Set the date label depending on the current time.
fn set_date(&self, epoch: i32) -> Result<(), Error> { fn set_date(&mut self, epoch: i32) {
let mut lock = self.date.lock().map_err(|err| format_err!("{}", err))?; let machine = self.date.get_mut();
take_mut::take(lock.deref_mut(), |date| { take_mut::take(machine, |date| date.determine_state(i64::from(epoch)));
date.determine_state(i64::from(epoch))
});
Ok(())
} }
/// Set the duration label. /// Set the duration label.
fn set_duration(&mut self, seconds: Option<i32>) -> Result<(), Error> { fn set_duration(&mut self, seconds: Option<i32>) {
let mut lock = self.duration.lock().map_err(|err| format_err!("{}", err))?; let machine = self.duration.get_mut();
take_mut::take(lock.deref_mut(), |duration| { take_mut::take(machine, |duration| duration.determine_state(seconds));
duration.determine_state(seconds)
});
Ok(())
} }
fn determine_media_state(&self, episode: &EpisodeWidgetQuery) -> Result<(), Error> { fn determine_media_state(&self, episode: &EpisodeWidgetQuery) -> Result<(), Error> {
@ -222,14 +210,14 @@ fn on_download_clicked(ep: &EpisodeWidgetQuery, sender: Sender<Action>) -> Resul
#[inline] #[inline]
fn on_play_bttn_clicked( fn on_play_bttn_clicked(
episode: &mut EpisodeWidgetQuery, episode: &mut EpisodeWidgetQuery,
title: Rc<Mutex<TitleMachine>>, title: Rc<RefCell<TitleMachine>>,
sender: Sender<Action>, sender: Sender<Action>,
) -> Result<(), Error> { ) -> Result<(), Error> {
open_uri(episode.rowid())?; open_uri(episode.rowid())?;
episode.set_played_now()?; episode.set_played_now()?;
let mut lock = title.lock().map_err(|err| format_err!("{}", err))?; let mut machine = title.try_borrow_mut()?;
take_mut::take(lock.deref_mut(), |title| { take_mut::take(machine.deref_mut(), |title| {
title.determine_state(episode.played().is_some()) title.determine_state(episode.played().is_some())
}); });