vcl/README.scheduler | 51 +--
vcl/inc/osx/saltimer.h |3 --
vcl/inc/saltimer.hxx | 44
vcl/inc/win/saltimer.h |7 +++---
vcl/osx/saltimer.cxx | 22 +---
vcl/win/app/saltimer.cxx | 18 ++--
6 files changed, 98 insertions(+), 47 deletions(-)
New commits:
commit da5cdcdeddf7bc21606b4cb64d8b1fc412146935
Author: Jan-Marek Glogowski
Date: Fri Sep 29 21:02:17 2017 +0200
Convert tick-based timer events to versioned ones
Instead of storing the system ticks in the timer event message
simply store a version.
Moves the version handling code into a VersionedEvent class,
inherited by WinSalTimer and AquaSalTimer.
Change-Id: I5add85031d36b3424a26a9ef798294cbfb00b2e4
Reviewed-on: https://gerrit.libreoffice.org/42959
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski
diff --git a/vcl/README.scheduler b/vcl/README.scheduler
index ac4a0dd698d4..8c5e64ba74c5 100644
--- a/vcl/README.scheduler
+++ b/vcl/README.scheduler
@@ -107,7 +107,7 @@ thread redirects using Qt::BlockingQueuedConnection.
== General: processing all current events for DoYield ==
This is easily implemented for all non-priority queue based implementations.
-Windows and MacOS both have a timestamp attached to their events / messages,
+Windows and macOS both have a timestamp attached to their events / messages,
so simply get the current time and just process anything < timestamp.
For the KDE backend this is already the default behaviour - single event
processing isn't even supported. The headless backend accomplishes this by
@@ -130,10 +130,27 @@ may block the main thread until some events happen.
Currently we wait on an extra conditional, which is cleared by the main event
loop.
-== MacOS implementation details ==
+== General: invalidation of elapsed timer event messages ==
+
+Since the system timer to run the scheduler is single-shot, there should never
+be more then one elapsed timer event in system event queue. When stopping or
+restarting the timer, we eventually have to remove the now invalid event from
+the queue.
+
+But for the Windows and macOS backends this may fail as they have delayed
+posting of events, so a consecutive remove after a post will actually yield no
+remove. On Windows we even get unwanted processing of events outside of the
+main event loop, which may call the Scheduler, as timer management is handled
+in critical scheduler code.
+
+To prevent these problems, we don't even try to remove these events, but
+invalidate them by versioning the timer events. Timer events with invalid
+versions are processed but simply don't run the scheduler.
+
+== macOS implementation details ==
Generally the Scheduler is handled as expected, except on resize, which is
-handled with different runloop-modes in MacOS. In case of a resize, the normal
+handled with different runloop-modes in macOS. In case of a resize, the normal
runloop is suspended in sendEvent, so we can't call the scheduler via posted
main loop-events. Instead the scheduler uses the timer again.
@@ -145,7 +162,7 @@ but we can prevent running any other SolarMutex based code.
Those wakeup
events must be ignored to prevent busy-locks. For more info read the "General:
main thread deferral" section.
-We can neither rely on MacOS dispatch_sync code block execution nor the
+We can neither rely on macOS dispatch_sync code block execution nor the
message handling, as both can't be prioritized or filtered and the first
does also not allow nested execution and is just processed in sequence.
@@ -153,29 +170,25 @@ There is also a workaround for a problem for pushing
tasks to an empty queue,
as [NSApp postEvent: ... atStart: NO] doesn't append the event, if the
message queue is empty.
-Probably that's the reason, why some code comments spoke of lost events and
-there was some distinct additional event processing implemented.
-
== Windows implementation details ==
Posted or sent event messages often trigger processing of WndProc in
PeekMessage, GetMessage or DispatchMessage, independently from the message to
fetch, remove or dispatch ("During this call, the system delivers pending,
nonqueued messages..."). Additionally messages have an inherited priority
-based on the function used to generate them. Even if WM_TIMER should have been
-the lowest prio, a posted WM_TIMER is processed with the prio of a posted
-message.
+based on the function used to generate them. Even if WM_TIMER messages should
+have the lowest priority, a manually posted WM_TIMER is processed with the
+priority of a PostMessage message.
-Therefore the current solution always starts a (threaded) timer even for the
-instant Idles and syncs to this timer message in the main dispatch loop.
-Using SwitchToThread(), this seem to work