Skip to content

Commit edf798b

Browse files
guzzitmvaneijkextrawurst
authored
Refactor async tags (follow up PR) (#1245)
* AsyncTags * Verify hash of last hash * Make default Tags notification 'FinishUnchanged' * fixed bug preventing tags from displaying Co-authored-by: Martijn van Eijk <[email protected]> Co-authored-by: extrawurst <[email protected]>
1 parent 1985fd2 commit edf798b

File tree

1 file changed

+95
-66
lines changed

1 file changed

+95
-66
lines changed

asyncgit/src/tags.rs

Lines changed: 95 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,29 @@
11
use crate::{
2+
asyncjob::{AsyncJob, AsyncSingleJob, RunParams},
23
error::Result,
34
hash,
45
sync::{self, RepoPath},
56
AsyncGitNotification,
67
};
78
use crossbeam_channel::Sender;
89
use std::{
9-
sync::{
10-
atomic::{AtomicUsize, Ordering},
11-
Arc, Mutex,
12-
},
10+
sync::{Arc, Mutex},
1311
time::{Duration, Instant},
1412
};
1513
use sync::Tags;
1614

1715
///
1816
#[derive(Default, Clone)]
19-
struct TagsResult {
17+
pub struct TagsResult {
2018
hash: u64,
2119
tags: Tags,
2220
}
2321

2422
///
2523
pub struct AsyncTags {
26-
last: Arc<Mutex<Option<(Instant, TagsResult)>>>,
24+
last: Option<(Instant, TagsResult)>,
2725
sender: Sender<AsyncGitNotification>,
28-
pending: Arc<AtomicUsize>,
26+
job: AsyncSingleJob<AsyncTagsJob>,
2927
repo: RepoPath,
3028
}
3129

@@ -37,30 +35,27 @@ impl AsyncTags {
3735
) -> Self {
3836
Self {
3937
repo,
40-
last: Arc::new(Mutex::new(None)),
38+
last: None,
4139
sender: sender.clone(),
42-
pending: Arc::new(AtomicUsize::new(0)),
40+
job: AsyncSingleJob::new(sender.clone()),
4341
}
4442
}
4543

4644
/// last fetched result
47-
pub fn last(&mut self) -> Result<Option<Tags>> {
48-
let last = self.last.lock()?;
49-
50-
Ok(last.clone().map(|last| last.1.tags))
45+
pub fn last(&self) -> Result<Option<Tags>> {
46+
Ok(self.last.as_ref().map(|result| result.1.tags.clone()))
5147
}
5248

5349
///
5450
pub fn is_pending(&self) -> bool {
55-
self.pending.load(Ordering::Relaxed) > 0
51+
self.job.is_pending()
5652
}
5753

58-
fn is_outdated(&self, dur: Duration) -> Result<bool> {
59-
let last = self.last.lock()?;
60-
61-
Ok(last
54+
///
55+
fn is_outdated(&self, dur: Duration) -> bool {
56+
self.last
6257
.as_ref()
63-
.map_or(true, |(last_time, _)| last_time.elapsed() > dur))
58+
.map_or(true, |(last_time, _)| last_time.elapsed() > dur)
6459
}
6560

6661
///
@@ -71,72 +66,106 @@ impl AsyncTags {
7166
) -> Result<()> {
7267
log::trace!("request");
7368

74-
if !force && self.is_pending() {
69+
if !force && self.job.is_pending() {
7570
return Ok(());
7671
}
7772

78-
let outdated = self.is_outdated(dur)?;
73+
let outdated = self.is_outdated(dur);
7974

8075
if !force && !outdated {
8176
return Ok(());
8277
}
8378

84-
let arc_last = Arc::clone(&self.last);
85-
let sender = self.sender.clone();
86-
let arc_pending = Arc::clone(&self.pending);
87-
88-
self.pending.fetch_add(1, Ordering::Relaxed);
8979
let repo = self.repo.clone();
9080

91-
rayon_core::spawn(move || {
92-
let notify = Self::getter(&repo, &arc_last, outdated)
93-
.expect("error getting tags");
94-
95-
arc_pending.fetch_sub(1, Ordering::Relaxed);
96-
97-
sender
98-
.send(if notify {
99-
AsyncGitNotification::Tags
100-
} else {
101-
AsyncGitNotification::FinishUnchanged
102-
})
103-
.expect("error sending notify");
104-
});
81+
if outdated {
82+
self.job.spawn(AsyncTagsJob::new(
83+
self.last
84+
.as_ref()
85+
.map_or(0, |(_, result)| result.hash),
86+
repo,
87+
));
88+
89+
if let Some(job) = self.job.take_last() {
90+
if let Some(Ok(result)) = job.result() {
91+
self.last = Some(result);
92+
}
93+
}
94+
} else {
95+
self.sender
96+
.send(AsyncGitNotification::FinishUnchanged)?;
97+
}
10598

10699
Ok(())
107100
}
101+
}
102+
103+
enum JobState {
104+
Request(u64, RepoPath),
105+
Response(Result<(Instant, TagsResult)>),
106+
}
108107

109-
fn getter(
110-
repo: &RepoPath,
111-
arc_last: &Arc<Mutex<Option<(Instant, TagsResult)>>>,
112-
outdated: bool,
113-
) -> Result<bool> {
114-
let tags = sync::get_tags(repo)?;
115-
116-
let hash = hash(&tags);
117-
118-
if !outdated
119-
&& Self::last_hash(arc_last)
120-
.map(|last| last == hash)
121-
.unwrap_or_default()
122-
{
123-
return Ok(false);
108+
///
109+
#[derive(Clone, Default)]
110+
pub struct AsyncTagsJob {
111+
state: Arc<Mutex<Option<JobState>>>,
112+
}
113+
114+
///
115+
impl AsyncTagsJob {
116+
///
117+
pub fn new(last_hash: u64, repo: RepoPath) -> Self {
118+
Self {
119+
state: Arc::new(Mutex::new(Some(JobState::Request(
120+
last_hash, repo,
121+
)))),
124122
}
123+
}
125124

126-
{
127-
let mut last = arc_last.lock()?;
128-
let now = Instant::now();
129-
*last = Some((now, TagsResult { hash, tags }));
125+
///
126+
pub fn result(&self) -> Option<Result<(Instant, TagsResult)>> {
127+
if let Ok(mut state) = self.state.lock() {
128+
if let Some(state) = state.take() {
129+
return match state {
130+
JobState::Request(_, _) => None,
131+
JobState::Response(result) => Some(result),
132+
};
133+
}
130134
}
131135

132-
Ok(true)
136+
None
133137
}
138+
}
139+
140+
impl AsyncJob for AsyncTagsJob {
141+
type Notification = AsyncGitNotification;
142+
type Progress = ();
143+
144+
fn run(
145+
&mut self,
146+
_params: RunParams<Self::Notification, Self::Progress>,
147+
) -> Result<Self::Notification> {
148+
let mut notification = AsyncGitNotification::FinishUnchanged;
149+
if let Ok(mut state) = self.state.lock() {
150+
*state = state.take().map(|state| match state {
151+
JobState::Request(last_hash, repo) => {
152+
let tags = sync::get_tags(&repo);
153+
154+
JobState::Response(tags.map(|tags| {
155+
let hash = hash(&tags);
156+
if last_hash != hash {
157+
notification = AsyncGitNotification::Tags;
158+
}
159+
160+
(Instant::now(), TagsResult { hash, tags })
161+
}))
162+
}
163+
JobState::Response(result) => {
164+
JobState::Response(result)
165+
}
166+
});
167+
}
134168

135-
fn last_hash(
136-
last: &Arc<Mutex<Option<(Instant, TagsResult)>>>,
137-
) -> Option<u64> {
138-
last.lock()
139-
.ok()
140-
.and_then(|last| last.as_ref().map(|(_, last)| last.hash))
169+
Ok(notification)
141170
}
142171
}

0 commit comments

Comments
 (0)