mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
LibCore: Make timer firing order stable for equal deadlines
Timers scheduled with identical `fire_time` could fire out of order because the heap is not stable. This change assigns a monotonically increasing `sequence_id` when a timer is scheduled and extend the heap comparator to order by (`fire_time`, `sequence_id`). This guarantees FIFO among timers with the same deadline. This matches the HTML "run steps after a timeout" ordering requirement: older invocations with <= delay complete before newer ones. https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#run-steps-after-a-timeout
This commit is contained in:
committed by
Sam Atkins
parent
1d41cf10f4
commit
de3f32a5c9
Notes:
github-actions[bot]
2025-09-22 11:35:38 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/de3f32a5c97 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6260 Reviewed-by: https://github.com/AtkinsSJ ✅
@@ -70,6 +70,9 @@ public:
|
||||
|
||||
bool is_scheduled() const { return m_index != INVALID_INDEX; }
|
||||
|
||||
void set_sequence_id(u64 id) { m_sequence_id = id; }
|
||||
u64 sequence_id() const { return m_sequence_id; }
|
||||
|
||||
protected:
|
||||
union {
|
||||
AK::Duration m_duration;
|
||||
@@ -78,6 +81,7 @@ protected:
|
||||
|
||||
private:
|
||||
ssize_t m_index = INVALID_INDEX;
|
||||
u64 m_sequence_id { 0 };
|
||||
};
|
||||
|
||||
class TimeoutSet {
|
||||
@@ -122,12 +126,14 @@ public:
|
||||
|
||||
void schedule_relative(EventLoopTimeout* timeout)
|
||||
{
|
||||
timeout->set_sequence_id(m_next_sequence_id++);
|
||||
timeout->set_index({}, -1 - static_cast<ssize_t>(m_scheduled_timeouts.size()));
|
||||
m_scheduled_timeouts.append(timeout);
|
||||
}
|
||||
|
||||
void schedule_absolute(EventLoopTimeout* timeout)
|
||||
{
|
||||
timeout->set_sequence_id(m_next_sequence_id++);
|
||||
m_heap.insert(timeout);
|
||||
}
|
||||
|
||||
@@ -160,6 +166,8 @@ private:
|
||||
IntrusiveBinaryHeap<
|
||||
EventLoopTimeout*,
|
||||
decltype([](EventLoopTimeout* a, EventLoopTimeout* b) {
|
||||
if (a->fire_time() == b->fire_time())
|
||||
return a->sequence_id() < b->sequence_id();
|
||||
return a->fire_time() < b->fire_time();
|
||||
}),
|
||||
decltype([](EventLoopTimeout* timeout, size_t index) {
|
||||
@@ -168,6 +176,7 @@ private:
|
||||
8>
|
||||
m_heap;
|
||||
Vector<EventLoopTimeout*, 8> m_scheduled_timeouts;
|
||||
u64 m_next_sequence_id { 0 };
|
||||
};
|
||||
|
||||
class EventLoopTimer final : public EventLoopTimeout {
|
||||
|
||||
Reference in New Issue
Block a user