Do not eagerly cancel running tasks
This commit is contained in:
parent
4d4544f680
commit
11fee4ce42
2 changed files with 115 additions and 46 deletions
|
@ -2632,7 +2632,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
InlayRefreshReason::NewLinesShown => InvalidationStrategy::None,
|
InlayRefreshReason::NewLinesShown => InvalidationStrategy::None,
|
||||||
InlayRefreshReason::ExcerptEdited => InvalidationStrategy::OnConflict,
|
InlayRefreshReason::ExcerptEdited => InvalidationStrategy::OnConflict,
|
||||||
InlayRefreshReason::RefreshRequested => InvalidationStrategy::All,
|
InlayRefreshReason::RefreshRequested => InvalidationStrategy::Forced,
|
||||||
};
|
};
|
||||||
|
|
||||||
let excerpts_to_query = self
|
let excerpts_to_query = self
|
||||||
|
@ -2680,7 +2680,6 @@ impl Editor {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(position, id, hint)| {
|
.map(|(position, id, hint)| {
|
||||||
let mut text = hint.text();
|
let mut text = hint.text();
|
||||||
// TODO kb styling instead?
|
|
||||||
if hint.padding_right {
|
if hint.padding_right {
|
||||||
text.push(' ');
|
text.push(' ');
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,17 @@ pub struct InlayHintCache {
|
||||||
pub hints: HashMap<ExcerptId, Arc<RwLock<CachedExcerptHints>>>,
|
pub hints: HashMap<ExcerptId, Arc<RwLock<CachedExcerptHints>>>,
|
||||||
pub allowed_hint_kinds: HashSet<Option<InlayHintKind>>,
|
pub allowed_hint_kinds: HashSet<Option<InlayHintKind>>,
|
||||||
pub version: usize,
|
pub version: usize,
|
||||||
update_tasks: HashMap<ExcerptId, InlayHintUpdateTask>,
|
update_tasks: HashMap<ExcerptId, UpdateTask>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InlayHintUpdateTask {
|
struct UpdateTask {
|
||||||
|
current: (InvalidationStrategy, SpawnedTask),
|
||||||
|
pending_refresh: Option<SpawnedTask>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpawnedTask {
|
||||||
version: usize,
|
version: usize,
|
||||||
|
is_running_rx: smol::channel::Receiver<()>,
|
||||||
_task: Task<()>,
|
_task: Task<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +57,31 @@ struct ExcerptDimensions {
|
||||||
excerpt_visible_range_end: language::Anchor,
|
excerpt_visible_range_end: language::Anchor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UpdateTask {
|
||||||
|
fn new(invalidation_strategy: InvalidationStrategy, spawned_task: SpawnedTask) -> Self {
|
||||||
|
Self {
|
||||||
|
current: (invalidation_strategy, spawned_task),
|
||||||
|
pending_refresh: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_running(&self) -> bool {
|
||||||
|
!self.current.1.is_running_rx.is_closed()
|
||||||
|
|| self
|
||||||
|
.pending_refresh
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |task| !task.is_running_rx.is_closed())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cache_version(&self) -> usize {
|
||||||
|
self.current.1.version
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidation_strategy(&self) -> InvalidationStrategy {
|
||||||
|
self.current.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ExcerptDimensions {
|
impl ExcerptDimensions {
|
||||||
fn contains_position(
|
fn contains_position(
|
||||||
&self,
|
&self,
|
||||||
|
@ -80,7 +111,7 @@ impl ExcerptDimensions {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum InvalidationStrategy {
|
pub enum InvalidationStrategy {
|
||||||
All,
|
Forced,
|
||||||
OnConflict,
|
OnConflict,
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
@ -157,7 +188,7 @@ impl InlayHintCache {
|
||||||
let update_tasks = &mut self.update_tasks;
|
let update_tasks = &mut self.update_tasks;
|
||||||
let invalidate_cache = matches!(
|
let invalidate_cache = matches!(
|
||||||
invalidate,
|
invalidate,
|
||||||
InvalidationStrategy::All | InvalidationStrategy::OnConflict
|
InvalidationStrategy::Forced | InvalidationStrategy::OnConflict
|
||||||
);
|
);
|
||||||
if invalidate_cache {
|
if invalidate_cache {
|
||||||
update_tasks
|
update_tasks
|
||||||
|
@ -166,22 +197,7 @@ impl InlayHintCache {
|
||||||
let cache_version = self.version;
|
let cache_version = self.version;
|
||||||
excerpts_to_query.retain(|visible_excerpt_id, _| {
|
excerpts_to_query.retain(|visible_excerpt_id, _| {
|
||||||
match update_tasks.entry(*visible_excerpt_id) {
|
match update_tasks.entry(*visible_excerpt_id) {
|
||||||
hash_map::Entry::Occupied(o) => match o.get().version.cmp(&cache_version) {
|
hash_map::Entry::Occupied(o) => match o.get().cache_version().cmp(&cache_version) {
|
||||||
cmp::Ordering::Less => true,
|
|
||||||
cmp::Ordering::Equal => invalidate_cache,
|
|
||||||
cmp::Ordering::Greater => false,
|
|
||||||
},
|
|
||||||
hash_map::Entry::Vacant(_) => true,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if invalidate_cache {
|
|
||||||
update_tasks
|
|
||||||
.retain(|task_excerpt_id, _| excerpts_to_query.contains_key(task_excerpt_id));
|
|
||||||
}
|
|
||||||
excerpts_to_query.retain(|visible_excerpt_id, _| {
|
|
||||||
match update_tasks.entry(*visible_excerpt_id) {
|
|
||||||
hash_map::Entry::Occupied(o) => match o.get().version.cmp(&cache_version) {
|
|
||||||
cmp::Ordering::Less => true,
|
cmp::Ordering::Less => true,
|
||||||
cmp::Ordering::Equal => invalidate_cache,
|
cmp::Ordering::Equal => invalidate_cache,
|
||||||
cmp::Ordering::Greater => false,
|
cmp::Ordering::Greater => false,
|
||||||
|
@ -313,8 +329,8 @@ impl InlayHintCache {
|
||||||
fn spawn_new_update_tasks(
|
fn spawn_new_update_tasks(
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Range<usize>)>,
|
excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Range<usize>)>,
|
||||||
invalidate: InvalidationStrategy,
|
invalidation_strategy: InvalidationStrategy,
|
||||||
cache_version: usize,
|
update_cache_version: usize,
|
||||||
cx: &mut ViewContext<'_, '_, Editor>,
|
cx: &mut ViewContext<'_, '_, Editor>,
|
||||||
) {
|
) {
|
||||||
let visible_hints = Arc::new(visible_inlay_hints(editor, cx).cloned().collect::<Vec<_>>());
|
let visible_hints = Arc::new(visible_inlay_hints(editor, cx).cloned().collect::<Vec<_>>());
|
||||||
|
@ -323,20 +339,26 @@ fn spawn_new_update_tasks(
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
let buffer_snapshot = buffer.snapshot();
|
let buffer_snapshot = buffer.snapshot();
|
||||||
let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
|
let cached_excerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
|
||||||
if let Some(cached_excerpt_hints) = &cached_excerpt_hints {
|
let cache_is_empty = match &cached_excerpt_hints {
|
||||||
let new_task_buffer_version = buffer_snapshot.version();
|
Some(cached_excerpt_hints) => {
|
||||||
let cached_excerpt_hints = cached_excerpt_hints.read();
|
let new_task_buffer_version = buffer_snapshot.version();
|
||||||
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
|
let cached_excerpt_hints = cached_excerpt_hints.read();
|
||||||
if cached_buffer_version.changed_since(new_task_buffer_version) {
|
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
|
||||||
return;
|
if cached_excerpt_hints.version > update_cache_version
|
||||||
|
|| cached_buffer_version.changed_since(new_task_buffer_version)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !new_task_buffer_version.changed_since(&cached_buffer_version)
|
||||||
|
&& !matches!(invalidation_strategy, InvalidationStrategy::Forced)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cached_excerpt_hints.hints.is_empty()
|
||||||
}
|
}
|
||||||
// TODO kb on refresh (InvalidationStrategy::All), instead spawn a new task afterwards, that would wait before 1st query finishes
|
None => true,
|
||||||
if !new_task_buffer_version.changed_since(&cached_buffer_version)
|
};
|
||||||
&& !matches!(invalidate, InvalidationStrategy::All)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let buffer_id = buffer.remote_id();
|
let buffer_id = buffer.remote_id();
|
||||||
let excerpt_visible_range_start = buffer.anchor_before(excerpt_visible_range.start);
|
let excerpt_visible_range_start = buffer.anchor_before(excerpt_visible_range.start);
|
||||||
|
@ -365,21 +387,62 @@ fn spawn_new_update_tasks(
|
||||||
excerpt_visible_range_start,
|
excerpt_visible_range_start,
|
||||||
excerpt_visible_range_end,
|
excerpt_visible_range_end,
|
||||||
},
|
},
|
||||||
cache_version,
|
cache_version: update_cache_version,
|
||||||
invalidate,
|
invalidate: invalidation_strategy,
|
||||||
};
|
};
|
||||||
|
|
||||||
editor.inlay_hint_cache.update_tasks.insert(
|
let new_update_task = |previous_task| {
|
||||||
excerpt_id,
|
|
||||||
new_update_task(
|
new_update_task(
|
||||||
query,
|
query,
|
||||||
multi_buffer_snapshot,
|
multi_buffer_snapshot,
|
||||||
buffer_snapshot,
|
buffer_snapshot,
|
||||||
Arc::clone(&visible_hints),
|
Arc::clone(&visible_hints),
|
||||||
cached_excerpt_hints,
|
cached_excerpt_hints,
|
||||||
|
previous_task,
|
||||||
cx,
|
cx,
|
||||||
),
|
)
|
||||||
);
|
};
|
||||||
|
match editor.inlay_hint_cache.update_tasks.entry(excerpt_id) {
|
||||||
|
hash_map::Entry::Occupied(mut o) => {
|
||||||
|
let update_task = o.get_mut();
|
||||||
|
if update_task.is_running() {
|
||||||
|
match (update_task.invalidation_strategy(), invalidation_strategy) {
|
||||||
|
(InvalidationStrategy::Forced, InvalidationStrategy::Forced)
|
||||||
|
| (_, InvalidationStrategy::OnConflict) => {
|
||||||
|
o.insert(UpdateTask::new(
|
||||||
|
invalidation_strategy,
|
||||||
|
new_update_task(None),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
(InvalidationStrategy::Forced, _) => {}
|
||||||
|
(_, InvalidationStrategy::Forced) => {
|
||||||
|
if cache_is_empty {
|
||||||
|
o.insert(UpdateTask::new(
|
||||||
|
invalidation_strategy,
|
||||||
|
new_update_task(None),
|
||||||
|
));
|
||||||
|
} else if update_task.pending_refresh.is_none() {
|
||||||
|
update_task.pending_refresh = Some(new_update_task(Some(
|
||||||
|
update_task.current.1.is_running_rx.clone(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
o.insert(UpdateTask::new(
|
||||||
|
invalidation_strategy,
|
||||||
|
new_update_task(None),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_map::Entry::Vacant(v) => {
|
||||||
|
v.insert(UpdateTask::new(
|
||||||
|
invalidation_strategy,
|
||||||
|
new_update_task(None),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,10 +454,16 @@ fn new_update_task(
|
||||||
buffer_snapshot: BufferSnapshot,
|
buffer_snapshot: BufferSnapshot,
|
||||||
visible_hints: Arc<Vec<Inlay>>,
|
visible_hints: Arc<Vec<Inlay>>,
|
||||||
cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
|
cached_excerpt_hints: Option<Arc<RwLock<CachedExcerptHints>>>,
|
||||||
|
previous_task: Option<smol::channel::Receiver<()>>,
|
||||||
cx: &mut ViewContext<'_, '_, Editor>,
|
cx: &mut ViewContext<'_, '_, Editor>,
|
||||||
) -> InlayHintUpdateTask {
|
) -> SpawnedTask {
|
||||||
let hints_fetch_tasks = hints_fetch_tasks(query, &buffer_snapshot, cx);
|
let hints_fetch_tasks = hints_fetch_tasks(query, &buffer_snapshot, cx);
|
||||||
|
let (is_running_tx, is_running_rx) = smol::channel::bounded(1);
|
||||||
let _task = cx.spawn(|editor, cx| async move {
|
let _task = cx.spawn(|editor, cx| async move {
|
||||||
|
let _is_running_tx = is_running_tx;
|
||||||
|
if let Some(previous_task) = previous_task {
|
||||||
|
previous_task.recv().await.ok();
|
||||||
|
}
|
||||||
let create_update_task = |range, hint_fetch_task| {
|
let create_update_task = |range, hint_fetch_task| {
|
||||||
fetch_and_update_hints(
|
fetch_and_update_hints(
|
||||||
editor.clone(),
|
editor.clone(),
|
||||||
|
@ -437,9 +506,10 @@ fn new_update_task(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
InlayHintUpdateTask {
|
SpawnedTask {
|
||||||
version: query.cache_version,
|
version: query.cache_version,
|
||||||
_task,
|
_task,
|
||||||
|
is_running_rx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,7 +667,7 @@ fn calculate_hint_updates(
|
||||||
let mut remove_from_cache = HashSet::default();
|
let mut remove_from_cache = HashSet::default();
|
||||||
if matches!(
|
if matches!(
|
||||||
query.invalidate,
|
query.invalidate,
|
||||||
InvalidationStrategy::All | InvalidationStrategy::OnConflict
|
InvalidationStrategy::Forced | InvalidationStrategy::OnConflict
|
||||||
) {
|
) {
|
||||||
remove_from_visible.extend(
|
remove_from_visible.extend(
|
||||||
visible_hints
|
visible_hints
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue