mirror of https://github.com/adamdruppe/arsd.git
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:
parent
d61f339e41
commit
dd2f7a60a0
|
@ -3375,6 +3375,7 @@ struct EventLoopImpl {
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
MSG message;
|
MSG message;
|
||||||
while(ret != 0 && (whileCondition is null || whileCondition() == true) && notExited) {
|
while(ret != 0 && (whileCondition is null || whileCondition() == true) && notExited) {
|
||||||
|
eventLoopRound++;
|
||||||
auto wto = SimpleWindow.eventAllQueueTimeoutMSecs();
|
auto wto = SimpleWindow.eventAllQueueTimeoutMSecs();
|
||||||
auto waitResult = MsgWaitForMultipleObjectsEx(
|
auto waitResult = MsgWaitForMultipleObjectsEx(
|
||||||
cast(int) handles.length, handles.ptr,
|
cast(int) handles.length, handles.ptr,
|
||||||
|
@ -4318,6 +4319,7 @@ class Timer {
|
||||||
this(int intervalInMilliseconds, void delegate() onPulse) {
|
this(int intervalInMilliseconds, void delegate() onPulse) {
|
||||||
assert(onPulse !is null);
|
assert(onPulse !is null);
|
||||||
|
|
||||||
|
this.intervalInMilliseconds = intervalInMilliseconds;
|
||||||
this.onPulse = onPulse;
|
this.onPulse = onPulse;
|
||||||
|
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
|
@ -4329,7 +4331,7 @@ class Timer {
|
||||||
|
|
||||||
// thanks to Archival 998 for the WaitableTimer blocks
|
// thanks to Archival 998 for the WaitableTimer blocks
|
||||||
handle = CreateWaitableTimer(null, false, null);
|
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))
|
if(handle is null || !SetWaitableTimer(handle, cast(LARGE_INTEGER*)&initialTime, intervalInMilliseconds, &timerCallback, handle, false))
|
||||||
throw new Exception("SetWaitableTimer Failed");
|
throw new Exception("SetWaitableTimer Failed");
|
||||||
|
|
||||||
|
@ -4370,6 +4372,8 @@ class Timer {
|
||||||
} else featureNotImplemented();
|
} else featureNotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int intervalInMilliseconds;
|
||||||
|
|
||||||
/// Stop and destroy the timer object.
|
/// Stop and destroy the timer object.
|
||||||
void destroy() {
|
void destroy() {
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
|
@ -4409,12 +4413,13 @@ class Timer {
|
||||||
|
|
||||||
void changeTime(int intervalInMilliseconds)
|
void changeTime(int intervalInMilliseconds)
|
||||||
{
|
{
|
||||||
|
this.intervalInMilliseconds = intervalInMilliseconds;
|
||||||
version(Windows)
|
version(Windows)
|
||||||
{
|
{
|
||||||
if(handle)
|
if(handle)
|
||||||
{
|
{
|
||||||
//handle = SetTimer(null, handle, intervalInMilliseconds, &timerCallback);
|
//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))
|
if(handle is null || !SetWaitableTimer(handle, cast(LARGE_INTEGER*)&initialTime, intervalInMilliseconds, &timerCallback, handle, false))
|
||||||
throw new Exception("couldn't change pulse timer");
|
throw new Exception("couldn't change pulse timer");
|
||||||
}
|
}
|
||||||
|
@ -4426,18 +4431,27 @@ class Timer {
|
||||||
|
|
||||||
void delegate() onPulse;
|
void delegate() onPulse;
|
||||||
|
|
||||||
|
int lastEventLoopRoundTriggered;
|
||||||
|
|
||||||
void trigger() {
|
void trigger() {
|
||||||
version(linux) {
|
version(linux) {
|
||||||
import unix = core.sys.posix.unistd;
|
import unix = core.sys.posix.unistd;
|
||||||
long val;
|
long val;
|
||||||
unix.read(fd, &val, val.sizeof); // gotta clear the pipe
|
unix.read(fd, &val, val.sizeof); // gotta clear the pipe
|
||||||
} else version(Windows) {
|
} else version(Windows) {
|
||||||
|
if(this.lastEventLoopRoundTriggered == eventLoopRound)
|
||||||
|
return; // never try to actually run faster than the event loop
|
||||||
|
lastEventLoopRoundTriggered = eventLoopRound;
|
||||||
} else featureNotImplemented();
|
} else featureNotImplemented();
|
||||||
|
|
||||||
onPulse();
|
onPulse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
void rearm() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
version(Windows)
|
version(Windows)
|
||||||
extern(Windows)
|
extern(Windows)
|
||||||
//static void timerCallback(HWND, UINT, UINT_PTR timer, DWORD dwTime) nothrow {
|
//static void timerCallback(HWND, UINT, UINT_PTR timer, DWORD dwTime) nothrow {
|
||||||
|
@ -4461,6 +4475,9 @@ class Timer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
private int eventLoopRound;
|
||||||
|
|
||||||
version(Windows)
|
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
|
/// 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 {
|
class WindowsHandleReader {
|
||||||
|
|
Loading…
Reference in New Issue