optimize all async job related clones away (#725)

This commit is contained in:
Stephan Dilly 2021-05-24 02:15:52 +02:00
parent f73cfa01f1
commit a8bf31b0ab
4 changed files with 52 additions and 35 deletions

View file

@ -66,10 +66,10 @@ impl<J: 'static + AsyncJob, T: Copy + Send + 'static>
false false
} }
/// return clone of last result ///
pub fn get_last(&self) -> Option<J> { pub fn take_last(&self) -> Option<J> {
if let Ok(last) = self.last.lock() { if let Ok(mut last) = self.last.lock() {
last.clone() last.take()
} else { } else {
None None
} }

View file

@ -173,11 +173,7 @@ impl RevisionFilesComponent {
} }
} }
fn draw_tree<B: Backend>( fn draw_tree<B: Backend>(&self, f: &mut Frame<B>, area: Rect) {
&self,
f: &mut Frame<B>,
area: Rect,
) -> Result<()> {
let tree_height = usize::from(area.height.saturating_sub(2)); let tree_height = usize::from(area.height.saturating_sub(2));
let selection = self.tree.visual_selection(); let selection = self.tree.visual_selection();
@ -203,18 +199,6 @@ impl RevisionFilesComponent {
Self::tree_item_to_span(item, &self.theme, selected) Self::tree_item_to_span(item, &self.theme, selected)
}); });
f.render_widget(Clear, area);
f.render_widget(
Block::default()
.borders(Borders::TOP)
.title(Span::styled(
format!(" {}", self.title),
self.theme.title(true),
))
.border_style(self.theme.block(true)),
area,
);
let is_tree_focused = matches!(self.focus, Focus::Tree); let is_tree_focused = matches!(self.focus, Focus::Tree);
ui::draw_list_block( ui::draw_list_block(
@ -235,8 +219,6 @@ impl RevisionFilesComponent {
self.scroll_top.get(), self.scroll_top.get(),
); );
} }
Ok(())
} }
} }
@ -259,7 +241,19 @@ impl DrawableComponent for RevisionFilesComponent {
) )
.split(area); .split(area);
self.draw_tree(f, chunks[0])?; f.render_widget(Clear, area);
f.render_widget(
Block::default()
.borders(Borders::TOP)
.title(Span::styled(
format!(" {}", self.title),
self.theme.title(true),
))
.border_style(self.theme.block(true)),
area,
);
self.draw_tree(f, chunks[0]);
self.current_file.draw(f, chunks[1])?; self.current_file.draw(f, chunks[1])?;
} }

View file

@ -61,11 +61,11 @@ impl SyntaxTextComponent {
/// ///
pub fn update(&mut self, ev: AsyncNotification) { pub fn update(&mut self, ev: AsyncNotification) {
if ev == AsyncNotification::SyntaxHighlighting { if ev == AsyncNotification::SyntaxHighlighting {
if let Some(job) = self.async_highlighting.get_last() { if let Some(job) = self.async_highlighting.take_last() {
if let Some((path, content)) = if let Some((path, content)) =
self.current_file.as_mut() self.current_file.as_mut()
{ {
if let Some(syntax) = (*job.text).clone() { if let Some(syntax) = job.result() {
if syntax.path() == Path::new(path) { if syntax.path() == Path::new(path) {
*content = Either::Left(syntax); *content = Either::Left(syntax);
} }

View file

@ -5,7 +5,7 @@ use std::{
ffi::OsStr, ffi::OsStr,
ops::Range, ops::Range,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::{Arc, Mutex},
}; };
use syntect::{ use syntect::{
highlighting::{ highlighting::{
@ -145,27 +145,50 @@ fn syntact_style_to_tui(style: &Style) -> tui::style::Style {
res res
} }
enum JobState {
Request((String, String)),
Response(SyntaxText),
}
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct AsyncSyntaxJob { pub struct AsyncSyntaxJob {
//TODO: can we merge input and text into a single enum to represent the state transition? state: Arc<Mutex<Option<JobState>>>,
pub input: Option<(String, String)>,
pub text: Arc<Option<SyntaxText>>,
} }
impl AsyncSyntaxJob { impl AsyncSyntaxJob {
pub fn new(content: String, path: String) -> Self { pub fn new(content: String, path: String) -> Self {
Self { Self {
input: Some((content, path)), state: Arc::new(Mutex::new(Some(JobState::Request((
text: Arc::new(None), content, path,
))))),
} }
} }
pub fn result(&self) -> Option<SyntaxText> {
if let Ok(mut state) = self.state.lock() {
if let Some(state) = state.take() {
return match state {
JobState::Request(_) => None,
JobState::Response(text) => Some(text),
};
}
}
None
}
} }
impl AsyncJob for AsyncSyntaxJob { impl AsyncJob for AsyncSyntaxJob {
fn run(&mut self) { fn run(&mut self) {
if let Some((text, path)) = self.input.take() { if let Ok(mut state) = self.state.lock() {
let syntax = SyntaxText::new(text, Path::new(&path)); *state = state.take().map(|state| match state {
self.text = Arc::new(Some(syntax)); JobState::Request((content, path)) => {
let syntax =
SyntaxText::new(content, Path::new(&path));
JobState::Response(syntax)
}
JobState::Response(res) => JobState::Response(res),
});
} }
} }
} }