diff --git a/notify-debouncer-full/src/lib.rs b/notify-debouncer-full/src/lib.rs index 18262edd..6870f853 100644 --- a/notify-debouncer-full/src/lib.rs +++ b/notify-debouncer-full/src/lib.rs @@ -62,7 +62,8 @@ mod cache; mod testing; use std::{ - collections::{HashMap, VecDeque}, + cmp::Reverse, + collections::{BinaryHeap, HashMap, VecDeque}, path::{Path, PathBuf}, sync::{ atomic::{AtomicBool, Ordering}, @@ -716,21 +717,31 @@ fn sort_events(events: Vec) -> Vec { }); // push events for different paths in chronological order and keep the order of events with the same path - while !events_by_path.is_empty() { - let min_time = events_by_path - .values() - .map(|events| events[0].time) - .min() - .unwrap(); - - for events in events_by_path.values_mut() { - while events.front().is_some_and(|event| event.time <= min_time) { - let event = events.pop_front().unwrap(); - sorted.push(event); - } + + let mut min_time_heap = events_by_path + .iter() + .map(|(path, events)| Reverse((events[0].time, path.clone()))) + .collect::>(); + + while let Some(Reverse((min_time, path))) = min_time_heap.pop() { + // unwrap is safe because only paths from `events_by_path` are added to `min_time_heap` + // and they are never removed from `events_by_path`. + let events = events_by_path.get_mut(&path).unwrap(); + + let mut push_next = false; + + while events.front().is_some_and(|event| event.time <= min_time) { + // unwrap is safe beause `pop_front` mus return some in order to enter the loop + let event = events.pop_front().unwrap(); + sorted.push(event); + push_next = true; } - events_by_path.retain(|_, events| !events.is_empty()); + if push_next { + if let Some(event) = events.front() { + min_time_heap.push(Reverse((event.time, path))); + } + } } sorted