ensure timer guts never called more than once per event loop round to ensure it doesnt lock up the nromal event handling message pump

This commit is contained in:
Adam D. Ruppe 2020-12-09 14:39:08 -05:00
parent d61f339e41
commit dd2f7a60a0
1 changed files with 20 additions and 3 deletions

View File

@ -3375,6 +3375,7 @@ struct EventLoopImpl {
int ret = -1;
MSG message;
while(ret != 0 && (whileCondition is null || whileCondition() == true) && notExited) {
eventLoopRound++;
auto wto = SimpleWindow.eventAllQueueTimeoutMSecs();
auto waitResult = MsgWaitForMultipleObjectsEx(
cast(int) handles.length, handles.ptr,
@ -4318,6 +4319,7 @@ class Timer {
this(int intervalInMilliseconds, void delegate() onPulse) {
assert(onPulse !is null);
this.intervalInMilliseconds = intervalInMilliseconds;
this.onPulse = onPulse;
version(Windows) {
@ -4329,7 +4331,7 @@ class Timer {
// thanks to Archival 998 for the WaitableTimer blocks
handle = CreateWaitableTimer(null, false, null);
long initialTime = 0;
long initialTime = -intervalInMilliseconds;
if(handle is null || !SetWaitableTimer(handle, cast(LARGE_INTEGER*)&initialTime, intervalInMilliseconds, &timerCallback, handle, false))
throw new Exception("SetWaitableTimer Failed");
@ -4370,6 +4372,8 @@ class Timer {
} else featureNotImplemented();
}
private int intervalInMilliseconds;
/// Stop and destroy the timer object.
void destroy() {
version(Windows) {
@ -4409,12 +4413,13 @@ class Timer {
void changeTime(int intervalInMilliseconds)
{
this.intervalInMilliseconds = intervalInMilliseconds;
version(Windows)
{
if(handle)
{
//handle = SetTimer(null, handle, intervalInMilliseconds, &timerCallback);
long initialTime = 0;
long initialTime = -intervalInMilliseconds;
if(handle is null || !SetWaitableTimer(handle, cast(LARGE_INTEGER*)&initialTime, intervalInMilliseconds, &timerCallback, handle, false))
throw new Exception("couldn't change pulse timer");
}
@ -4426,18 +4431,27 @@ class Timer {
void delegate() onPulse;
int lastEventLoopRoundTriggered;
void trigger() {
version(linux) {
import unix = core.sys.posix.unistd;
long val;
unix.read(fd, &val, val.sizeof); // gotta clear the pipe
} else version(Windows) {
if(this.lastEventLoopRoundTriggered == eventLoopRound)
return; // never try to actually run faster than the event loop
lastEventLoopRoundTriggered = eventLoopRound;
} else featureNotImplemented();
onPulse();
}
version(Windows)
void rearm() {
}
version(Windows)
extern(Windows)
//static void timerCallback(HWND, UINT, UINT_PTR timer, DWORD dwTime) nothrow {
@ -4461,6 +4475,9 @@ class Timer {
}
}
version(Windows)
private int eventLoopRound;
version(Windows)
/// Lets you add HANDLEs to the event loop. Not meant to be used for async I/O per se, but for other handles (it can only handle a few handles at a time.) Only works on certain types of handles! see: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-msgwaitformultipleobjectsex
class WindowsHandleReader {