SDL_WaitEvent not waking up properly?

Hi,

Windows 10 SDL2 user here!

I’m using an SDL timer to SDL_PushEvent a user event to the event queue,
but this does not appear to be ‘waking up’ SDL_WaitEvent immediately -
there’s some weird delay between when I push the event (from the timer
thread) and when SDL_WaitEvent wakes up.

However, if I replace this:

SDL_WaitEvent( Null );
ProcessEvents(); //polls/pops events

…with this…

SDL_Delay(1);
ProcessEvents();

It all starts to work properly, ie: timer user events are processed
immediately.

With SDL_WaitEvent, the delivery of the user event gets ‘delayed’ by some
amount of time - or more precisely, appears to be ‘quantized’ to 10ms-ish.

I have tried both SDL_PushEvent and SDL_PeepEvents from the timer thread,
same result.

Is this expected behaviour of SDL_WaitEvent? Does it always wait at least
10ms or something? Can it not be interrupted by pushing an event?

Bye!
Mark

Ok, just found the SDL_Delay(10) in SDL_WaitEventTimeout()!

This is a bit disappointing. I had assumed all the event queue stuff was
properly synchronized, but this throws a big nasty 10ms spanner in the
works!

Oh well, at least I know what’s going on now.On Sun, May 22, 2016 at 10:26 AM, Mark Sibly <@Mark_Sibly> wrote:

Hi,

Windows 10 SDL2 user here!

I’m using an SDL timer to SDL_PushEvent a user event to the event queue,
but this does not appear to be ‘waking up’ SDL_WaitEvent immediately -
there’s some weird delay between when I push the event (from the timer
thread) and when SDL_WaitEvent wakes up.

However, if I replace this:

SDL_WaitEvent( Null );
ProcessEvents(); //polls/pops events

…with this…

SDL_Delay(1);
ProcessEvents();

It all starts to work properly, ie: timer user events are processed
immediately.

With SDL_WaitEvent, the delivery of the user event gets ‘delayed’ by some
amount of time - or more precisely, appears to be ‘quantized’ to 10ms-ish.

I have tried both SDL_PushEvent and SDL_PeepEvents from the timer thread,
same result.

Is this expected behaviour of SDL_WaitEvent? Does it always wait at least
10ms or something? Can it not be interrupted by pushing an event?

Bye!
Mark

marksibly wrote:

This is a bit disappointing. I had assumed all the event queue stuff was properly synchronized, but this throws a big nasty 10ms spanner in the works!

I second that! I really miss ‘proper’ thread synchronization capabilities; my event-polling loop wastes a lot of CPU time spinning with no delay to achieve an acceptable latency. Would it not be possible for SDL to call WaitForSingleObject() in Windows or pthread_cond_timedwait() in Linux?

Richard.

Actually, I sort of got this going using a semaphore - it’s as ugly as hell
but seems to work in my code. Can share the code if you want, but it might
be a bit dodgy.

There also appears to be a bug in the timer logic - it ‘skips’ every now
and then if a tick happens at a certain place in the timer thread loop.

Perhaps the timer aren’t designed to be that accurate, but this prevented
me implementing a 60hz timer via the timer returning 16,17,17,16,17,17 etc.
intervals.

I’ve got a quick ‘n’ dirty fix for this too, but it probably needs
attention from someone who knows what they’re doing (if it is in fact a
bug).On Sun, May 22, 2016 at 9:46 PM, rtrussell wrote:

marksibly wrote:

This is a bit disappointing. I had assumed all the event queue stuff was
properly synchronized, but this throws a big nasty 10ms spanner in the
works!

I second that! I really miss ‘proper’ thread synchronization capabilities;
my event-polling loop wastes a lot of CPU time spinning with no delay to
achieve an acceptable latency. Would it not be possible for SDL to call
WaitForSingleObject() in Windows or pthread_cond_timedwait() in Linux?

Richard.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

marksibly wrote:

Actually, I sort of got this going using a semaphore

I use a semaphore too, but only as a means of signalling back to the ‘sending’ thread that the event has been read (I need a functionality like SendMessage in Windows).

I suppose the key question is whether SDL_SemWaitTimeout uses a more efficient waiting mechanism (in terms of latency and CPU usage) than SDL_WaitEventTimeout. If it does then I might be able to improve on my existing approach, but in that case why wouldn’t SDL do the same itself?

Richard.

I use a semaphore too, but only as a means of signalling back to the
’sending’ thread that the event has been read

My goal was basically to make WaitEvent block properly instead of ‘spin’. I
still like to do all my coding on the ‘main’ thread, so the timer callbacks
just push a user event and return very quickly. But this does mean
WaitEvent needs to be precise and not just delay(10) arbitrarily.

I got this going by posting to a semaphore in peepevents just after any
events are added, and doing a wait on this semaphore in WaitEvent instead
of the delay(10) when there are no events. The semaphore wait will often
return immediately here because I’m posting in peepevents more than I need
to, but that’s OK because it’ll eventually ‘flush’ the semaphore and block
for real. Not 100% nice, but better than just thrashing delay(0).

The real fix is probably to only post when an event as added to an empty
queue. The semaphore will still probably spin sometimes depending on how
events are being pulled from the queue, but it should be generally better.

I suppose the key question is whether SDL_SemWaitTimeout uses a more
efficient waiting mechanism

Good question. Looking at the code, the windows one does, but the linux one
only does if you have #defined HAVE_SEM_TIMEDWAIT - which I haven’t done
(yet)!

But the above fix doesn’t even need a timed semaphore now that I think
about it…On Mon, May 23, 2016 at 8:14 PM, rtrussell wrote:

marksibly wrote:

Actually, I sort of got this going using a semaphore

I use a semaphore too, but only as a means of signalling back to the
’sending’ thread that the event has been read (I need a functionality like
SendMessage in Windows).

I suppose the key question is whether SDL_SemWaitTimeout uses a more
efficient waiting mechanism (in terms of latency and CPU usage) than
SDL_WaitEventTimeout. If it does then I might be able to improve on my
existing approach, but in that case why wouldn’t SDL do the same itself?

Richard.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

marksibly wrote:

Looking at the code, the windows one does, but the linux one only does if you have #defined HAVE_SEM_TIMEDWAIT - which I haven’t done (yet)!

Presumably the HAVE_SEM_TIMEDWAIT is only useful if you’re rebuilding SDL from the source. Normally I will be using the pre-built SDL2.DLL in Windows and libsdl2.so in Linux. So I guess whether I can take advantage of a more efficient wait in SDL_SemWaitTimeout depends on how the standard Linux packages are compiled, and indeed what the reason for the #define is in the first place. Do you know?

But the above fix doesn’t even need a timed semaphore now that I think about it…

It would in my case because I’m creating my renderer with SDL_RENDERER_PRESENTVSYNC so once a frame I need it to spin in SDL_RenderPresent rather than waiting for an event to arrive. If there was some way of posting a user event synchronously with (and slightly before) the Vsync it would be different, but I don’t think there is.

Richard.