Skip to content

make scheduled/deferred task order deterministic#927

Closed
robnee wants to merge 1 commit intosolvespace:masterfrom
robnee:refreshTimer
Closed

make scheduled/deferred task order deterministic#927
robnee wants to merge 1 commit intosolvespace:masterfrom
robnee:refreshTimer

Conversation

@robnee
Copy link
Contributor

@robnee robnee commented Feb 7, 2021

Solvespace uses two timers (generateAllTimer and showTWTimer) to defer tasks until the event loop processing finishes. This helps coalesce multiple calls into one. You can call scheduleGenerateAll multiple times while processing UI messages but only trigger one GenerateAll. scheduleGenerateAll and scheduleShowTW do their scheuduling by setting timers with durations of zero. These timers fire (at least on Linux and Windows) some time after all other events in the message queue have been processed. This works fine when scheduling either one of these tasks. However, there is no guarantee in what order the timers will fire (at least on Windows) regardless of which order the scheduling calls are made. It's pretty easy to demonstrate (on some platforms) by adding logging to the scheduling calls and timer callbacks.

In many cases TextWindow::Show depends on generateAll happening first. This causes UI glitches where displays don't update and their contents are stale. Since this behavior is not deterministic it's easy to imagine how this problem could make certain bug reports difficult to reproduce and diagnose. #920 is a good example.
It also makes syncing up UI behavior across all platforms a challenge.

Solving this in the platform domain is tricky. This is PR endeavors to make the ordering of deferred calls to TextWindow::Show and generateAll deterministic. It does this by replacing generateAllTimer and showTWTimer with a single refreshTimer. Calls to scheduleGenerateAll and scheduleShowTW set flags to note the requested operations and schedule the refreshTimer. A new callback function SolveSpaceUI::Refresh can then check the flags and ensure that generateAll happens first. It fixes #920. Moreover, this PR makes it easy to observe and reproduce this problem reliably and across all platforms by simply reordering the calls in the Refresh callback.

It's pretty clear that the ordering is important so some solution is needed, if for no other reason than the sanity of the devs. I think this is a pretty good solution as it spells out the ordering. If nothing else this PR is helpful in further investigations.

@ruevs @phkahler I'd like to hear your thoughts.

@phkahler phkahler requested a review from ruevs February 7, 2021 22:51
@ruevs
Copy link
Member

ruevs commented Feb 7, 2021

Will look, 2-3 days.

@robnee
Copy link
Contributor Author

robnee commented Feb 8, 2021

@ruevs thanks. To be clear, I am not proposing this for 3.0 (maybe slap the 4.0 label on it) so I think we can take our time looking at this.

ruevs pushed a commit that referenced this pull request Jun 14, 2022
Fixes #920 #1143

Explanation from @robnee on Feb 7, 2021 in pull request #927

Solvespace uses two timers (generateAllTimer and showTWTimer) to defer tasks
until the event loop processing finishes. This helps coalesce multiple calls
into one. You can call scheduleGenerateAll multiple times while processing UI
messages but only trigger one GenerateAll. scheduleGenerateAll and
scheduleShowTW do their scheuduling by setting timers with durations of zero.
These timers fire (at least on Linux and Windows) some time after all other
events in the message queue have been processed. This works fine when
scheduling either one of these tasks. However, there is no guarantee in what
order the timers will fire (at least on Windows) regardless of which order the
scheduling calls are made. It's pretty easy to demonstrate (on some platforms)
by adding logging to the scheduling calls and timer callbacks.

In many cases TextWindow::Show depends on generateAll happening first. This
causes UI glitches where displays don't update and their contents are stale.
Since this behavior is not deterministic it's easy to imagine how this problem
could make certain bug reports difficult to reproduce and diagnose. #920 is a
good example. It also makes syncing up UI behavior across all platforms a
challenge.

Solving this in the platform domain is tricky. This is PR endeavors to make the
ordering of deferred calls to TextWindow::Show and generateAll deterministic.
It does this by replacing generateAllTimer and showTWTimer with a single
refreshTimer. Calls to scheduleGenerateAll and scheduleShowTW set flags to note
the requested operations and schedule the refreshTimer. A new callback function
SolveSpaceUI::Refresh can then check the flags and ensure that generateAll
happens first. It fixes #920. Moreover, this PR makes it easy to observe and
reproduce this problem reliably and across all platforms by simply reordering
the calls in the Refresh callback.

It's pretty clear that the ordering is important so some solution is needed, if
for no other reason than the sanity of the devs. I think this is a pretty good
solution as it spells out the ordering. If nothing else this PR is helpful in
further investigations.

@ruevs @phkahler I'd like to hear your thoughts.
@ruevs
Copy link
Member

ruevs commented Jun 14, 2022

@robnee it took me an year and three months instead of 2-3 days - and I apologize for this.

This is great and it totally makes sense it fixes #920 and #1143.

I rebased it on master here #1257 and will close this one.

@ruevs ruevs closed this Jun 14, 2022
phkahler pushed a commit that referenced this pull request Jun 14, 2022
Fixes #920 #1143

Explanation from @robnee on Feb 7, 2021 in pull request #927

Solvespace uses two timers (generateAllTimer and showTWTimer) to defer tasks
until the event loop processing finishes. This helps coalesce multiple calls
into one. You can call scheduleGenerateAll multiple times while processing UI
messages but only trigger one GenerateAll. scheduleGenerateAll and
scheduleShowTW do their scheuduling by setting timers with durations of zero.
These timers fire (at least on Linux and Windows) some time after all other
events in the message queue have been processed. This works fine when
scheduling either one of these tasks. However, there is no guarantee in what
order the timers will fire (at least on Windows) regardless of which order the
scheduling calls are made. It's pretty easy to demonstrate (on some platforms)
by adding logging to the scheduling calls and timer callbacks.

In many cases TextWindow::Show depends on generateAll happening first. This
causes UI glitches where displays don't update and their contents are stale.
Since this behavior is not deterministic it's easy to imagine how this problem
could make certain bug reports difficult to reproduce and diagnose. #920 is a
good example. It also makes syncing up UI behavior across all platforms a
challenge.

Solving this in the platform domain is tricky. This is PR endeavors to make the
ordering of deferred calls to TextWindow::Show and generateAll deterministic.
It does this by replacing generateAllTimer and showTWTimer with a single
refreshTimer. Calls to scheduleGenerateAll and scheduleShowTW set flags to note
the requested operations and schedule the refreshTimer. A new callback function
SolveSpaceUI::Refresh can then check the flags and ensure that generateAll
happens first. It fixes #920. Moreover, this PR makes it easy to observe and
reproduce this problem reliably and across all platforms by simply reordering
the calls in the Refresh callback.

It's pretty clear that the ordering is important so some solution is needed, if
for no other reason than the sanity of the devs. I think this is a pretty good
solution as it spells out the ordering. If nothing else this PR is helpful in
further investigations.

@ruevs @phkahler I'd like to hear your thoughts.
ruevs added a commit to ruevs/solvespace that referenced this pull request Nov 6, 2024
devin-ai-integration bot pushed a commit to erkinalp/solvespace that referenced this pull request Apr 3, 2025
Fixes solvespace#920 solvespace#1143

Explanation from @robnee on Feb 7, 2021 in pull request solvespace#927

Solvespace uses two timers (generateAllTimer and showTWTimer) to defer tasks
until the event loop processing finishes. This helps coalesce multiple calls
into one. You can call scheduleGenerateAll multiple times while processing UI
messages but only trigger one GenerateAll. scheduleGenerateAll and
scheduleShowTW do their scheuduling by setting timers with durations of zero.
These timers fire (at least on Linux and Windows) some time after all other
events in the message queue have been processed. This works fine when
scheduling either one of these tasks. However, there is no guarantee in what
order the timers will fire (at least on Windows) regardless of which order the
scheduling calls are made. It's pretty easy to demonstrate (on some platforms)
by adding logging to the scheduling calls and timer callbacks.

In many cases TextWindow::Show depends on generateAll happening first. This
causes UI glitches where displays don't update and their contents are stale.
Since this behavior is not deterministic it's easy to imagine how this problem
could make certain bug reports difficult to reproduce and diagnose. solvespace#920 is a
good example. It also makes syncing up UI behavior across all platforms a
challenge.

Solving this in the platform domain is tricky. This is PR endeavors to make the
ordering of deferred calls to TextWindow::Show and generateAll deterministic.
It does this by replacing generateAllTimer and showTWTimer with a single
refreshTimer. Calls to scheduleGenerateAll and scheduleShowTW set flags to note
the requested operations and schedule the refreshTimer. A new callback function
SolveSpaceUI::Refresh can then check the flags and ensure that generateAll
happens first. It fixes solvespace#920. Moreover, this PR makes it easy to observe and
reproduce this problem reliably and across all platforms by simply reordering
the calls in the Refresh callback.

It's pretty clear that the ordering is important so some solution is needed, if
for no other reason than the sanity of the devs. I think this is a pretty good
solution as it spells out the ordering. If nothing else this PR is helpful in
further investigations.

@ruevs @phkahler I'd like to hear your thoughts.
dennisyangji pushed a commit to Orthogonalpub/ode_solvespace that referenced this pull request Nov 25, 2025
Fixes solvespace#920 solvespace#1143

Explanation from @robnee on Feb 7, 2021 in pull request solvespace#927

Solvespace uses two timers (generateAllTimer and showTWTimer) to defer tasks
until the event loop processing finishes. This helps coalesce multiple calls
into one. You can call scheduleGenerateAll multiple times while processing UI
messages but only trigger one GenerateAll. scheduleGenerateAll and
scheduleShowTW do their scheuduling by setting timers with durations of zero.
These timers fire (at least on Linux and Windows) some time after all other
events in the message queue have been processed. This works fine when
scheduling either one of these tasks. However, there is no guarantee in what
order the timers will fire (at least on Windows) regardless of which order the
scheduling calls are made. It's pretty easy to demonstrate (on some platforms)
by adding logging to the scheduling calls and timer callbacks.

In many cases TextWindow::Show depends on generateAll happening first. This
causes UI glitches where displays don't update and their contents are stale.
Since this behavior is not deterministic it's easy to imagine how this problem
could make certain bug reports difficult to reproduce and diagnose. solvespace#920 is a
good example. It also makes syncing up UI behavior across all platforms a
challenge.

Solving this in the platform domain is tricky. This is PR endeavors to make the
ordering of deferred calls to TextWindow::Show and generateAll deterministic.
It does this by replacing generateAllTimer and showTWTimer with a single
refreshTimer. Calls to scheduleGenerateAll and scheduleShowTW set flags to note
the requested operations and schedule the refreshTimer. A new callback function
SolveSpaceUI::Refresh can then check the flags and ensure that generateAll
happens first. It fixes solvespace#920. Moreover, this PR makes it easy to observe and
reproduce this problem reliably and across all platforms by simply reordering
the calls in the Refresh callback.

It's pretty clear that the ordering is important so some solution is needed, if
for no other reason than the sanity of the devs. I think this is a pretty good
solution as it spells out the ordering. If nothing else this PR is helpful in
further investigations.

@ruevs @phkahler I'd like to hear your thoughts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"dof" in group list lags by "one click" after applying a constraint with the keyboard.

2 participants