Input Callback?

Hello!

I was tinkering with keyboard input the other day and I thought that it
would be nice to have a callback function that analysed keyboard input
whenever a keyboard event occured. I found the Event filter but I was
rather dissapointed when I read that you still have to call
SDL_PumpEvents() to get any events generated. The whole issue was that I
didn’t want to wait for my main gameloop to finish before I could
process input again. I solved it by placing input handling in a separate
thread.

But my real question boils down to: Why doesn’t SDL gather the events
automaticaly and pass it to a callback function (such as the event
filter)? Doesn’t most OS’s allow interupt filters to be installed in the
running kernel?(which SDL could do for you).

/Pontus

But my real question boils down to: Why doesn’t SDL gather the events
automaticaly and pass it to a callback function (such as the event
filter)? Doesn’t most OS’s allow interupt filters to be installed in the
running kernel?(which SDL could do for you).

Most don’t, actually.

Even when you get a “callback”, it’s because there’s some foundation
library that has hidden the lower level polling API from you.

–ryan.

[…asynchronous event input…]

I solved it by placing input handling in a separate
thread.

Well, that’s what SDL would have to do on most platforms anyway.
Why would you want a callback API, that basically just introduces
"hidden" synchronization issues?

IMHO, timestamped events would be much cleaner, more useful, more accurate, safer and more portable. :slight_smile:

But my real question boils down to: Why doesn’t SDL gather the events
automaticaly and pass it to a callback function (such as the event
filter)?

That would require an extra thread, which may be starved in some situations on operating systems with poor scheduling, and thus result in worse timing that you have now. It would also introduce sync issues between the event handling callback and the rest of the application, whether you need the feature or not.

Doesn’t most OS’s allow interupt filters to be installed in the
running kernel?

No, no current OSes support anything like that for normal event handling.

(To be correct though, I should perhaps mention that there are some “hacks” that do similar things to what you suggest. One would be Win2k “Kernel Streams” (audio processing), and another would be Mac OS “Classic”, which uses callbacks from interrupt context for audio.)

(which SDL could do for you).

Whatever API SDL uses, I think it should simply timestamp the events and throw them into the event queue.

Most applications should do fine by processing all pending events once per frame. For example, if you have a logic engine that runs at a fixed “virtual” frame rate (say 100 Hz), you could just calculate which frame every event belongs to, so you can process them at the right logic frame, instead of the normal “process all events before running the logic engine to the logic time of the next video frame.”

Networked real time games and the like could use a separate thread for event processing and networking, to ensure that input events get to the server and/or peers as fast as possible regardless of the video frame rate. (Exactly the same design as you would use for any mixed hard/soft real time system.)

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn Tue, 02/07/2002 18:05:00 , Pontus Pihlgren <pontus.pihlgren.5501 at student.uu.se> wrote:

[…asynchronous event input…]

>I solved it by placing input handling in a separate 
>thread.

Well, that's what SDL would have to do on most platforms anyway.
Why would you want a callback API, that basically just introduces
"hidden" synchronization issues?

IMHO, timestamped events would be much cleaner, more useful, more accurate, safer and more portable. :-)


>But my real question boils down to: Why doesn't SDL gather the events 
>automaticaly and pass it to a callback function (such as the event 
>filter)?

That would require an extra thread, which may be starved in some situations on operating systems with poor scheduling, and thus result in *worse* timing that you have now. It would also introduce sync issues  between the event handling callback and the rest of the application, whether you need the feature or not.


>Doesn't most OS's allow interupt filters to be installed in the 
>running kernel?

No, no current OSes support anything like that for normal event handling.

(To be correct though, I should perhaps mention that there are some "hacks" that do similar things to what you suggest. One would be Win2k "Kernel Streams" (audio processing), and another would be Mac OS "Classic", which uses callbacks from interrupt context for audio.)


>(which SDL could do for you).

Whatever API SDL uses, I think it should simply timestamp the events and throw them into the event queue.

Most applications should do fine by processing all pending events once per frame. For example, if you have a logic engine that runs at a fixed "virtual" frame rate (say 100 Hz), you could just calculate which frame every event belongs to, so you can process them at the right logic frame, instead of the normal "process all events before running the logic engine to the logic time of the next video frame."

Networked real time games and the like could use a separate thread for event processing and networking, to ensure that input events get to the server and/or peers as fast as possible regardless of the video frame rate. (Exactly the same design as you would use for any mixed hard/soft real time system.)

What is the advantage to setting a virtual logic frame rate like this as
opposed to just building your logic to accept arbitrary time indexes
whenever they are called.

At that point you can process events as quickly as you can read them and
just tell your logic the time index (or let it just read it from the
system) that the event occured at.

This is a genuine question more than a suggestion.

//David


.---------------------------------------
| David Olofson
| Programmer
| david.olofson at reologica.se
|---------------------------------------
| Address:
| REOLOGICA Instruments AB
| Scheelev?gen 30
| 223 63 LUND
| Sweden
|---------------------------------------
| Phone: 046-12 77 60
| Fax: 046-12 50 57
| Mobil: 
| E-mail: david.olofson at reologica.se
| WWW: http://www.reologica.se
| 
`-----> We Make Rheology RealOn Wed, 2002-07-03 at 11:38, David Olofson wrote:
On Tue, 02/07/2002 18:05:00 , Pontus Pihlgren <pontus.pihlgren.5501 at student.uu.se> wrote:


_______________________________________________
SDL mailing list
SDL at libsdl.org

http://www.libsdl.org/mailman/listinfo/sdl

End of Rant.

Jimmy
Jimmy’s World (http://www.jimmysworld.org)
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: This is a digitally signed message part
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020703/82eae77a/attachment.pgp

[…]

What is the advantage to setting a virtual logic frame rate like this as
opposed to just building your logic to accept arbitrary time indexes
whenever they are called.

It’s much easier to get right. If you allow varying logic frame rate, you run into issues with collision detection and events in general.

As an example; a simple

if(a and b collide)
    do_something_now();

becomes

if a and b will collide during the current frame
{
    t = when a and b actually collide;
    change_current_logic_time(t);
    do_something_now();
}

which cannot quite be implemented that “easilly” in a real game,
as you can’t move the current time back and forth arbitrarilly.
One way or another, you’ll have to keep track of all objects in
parallel, so that you can detect and process events in the right
order globally.

And of course, you need to be careful whenever an object changes
it’s movement speed. (Which happens constantly with acceleration…)
Not terribly complicated, but things add up - and in this area, it’s
easy to get it almost right and think that it actually works…

If you ignore this, you’ll end up with a game that behaves
slightly different at different frame rates.

At that point you can process events as quickly as you can read them and
just tell your logic the time index (or let it just read it from the
system) that the event occured at.

Yes, indeed, this would allow the engine to utilize whatever
timestamp resolution you may get - but the problem is to actually
implement it properly. (See above.)

That said, whith a sensible logic frame rate, and linear or
better interpolation of object movement, accuracy should be far
better than most games require anyway.

Speaking of which… runs off to write another post

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn 03/07/2002 14:59:31 , Jimmy wrote:

[…]
>What is the advantage to setting a virtual logic frame rate like this as
>opposed to just building your logic to accept arbitrary time indexes
>whenever they are called.

It's *much* easier to get right. If you allow varying logic frame rate, you run into issues with collision detection and events in general.

As an example; a simple

    if(a and b collide)
        do_something_now();

becomes

    if a and b will collide during the current frame
    {
        t = when a and b actually collide;
        change_current_logic_time(t);
        do_something_now();
    }

Ok, I’m basically sold on the idea… the only issue for me is that
logical frames will take place independently of visual frames (which is
good)… but since there isn’t timestamping of system events (even
though it would be nice), won’t there be control and logic
inconsistencies whenever a visual frame IS rendered because of the
likelyhood of missing a logic frame or two during a visual update?

Without the timestamp on the events, they’d bunch up during the visual
render.

I suppose this would be counteracted easily enough my capturing events
and queueing them, timestamped at the application level, during visual
updates. Or by making the logical framerate low enough to ensure no
frames are skipped during a render.

Is there a better way that I’m not seeing?
AND
Would the events taking place slightly out of order really be
perceptable since they would have all happened between visual frames
anyway, and the difference in motion paths would likely be trivial.

which cannot quite be implemented that "easilly" in a real game,
as you can't move the current time back and forth arbitrarilly.
One way or another, you'll have to keep track of all objects in
parallel, so that you can detect and process events in the right
order globally.

And of course, you need to be careful whenever an object changes
it's movement speed. (Which happens constantly with acceleration...)
Not terribly complicated, but things add up - and in this area, it's
easy to get it *almost* right and think that it actually works...

If you ignore this, you'll end up with a game that behaves
slightly different at different frame rates.


>At that point you can process events as quickly as you can read them and
>just tell your logic the time index (or let it just read it from the
>system) that the event occured at.

Yes, indeed, this would allow the engine to utilize whatever
timestamp resolution you may get - but the problem is to actually
implement it properly. (See above.)

That said, whith a sensible logic frame rate, and linear or
better interpolation of object movement, accuracy should be far
better than most games require anyway.


Speaking of which... *runs off to write another post*



//David


.---------------------------------------
| David Olofson
| Programmer
| david.olofson at reologica.se
|---------------------------------------
| Address:
| REOLOGICA Instruments AB
| Scheelev?gen 30
| 223 63 LUND
| Sweden
|---------------------------------------
| Phone: 046-12 77 60
| Fax: 046-12 50 57
| Mobil: 
| E-mail: david.olofson at reologica.se
| WWW: http://www.reologica.se
| 
`-----> We Make Rheology RealOn Wed, 2002-07-03 at 15:57, David Olofson wrote:
On 03/07/2002 14:59:31 , Jimmy <@Jimmy> wrote:


_______________________________________________
SDL mailing list
SDL at libsdl.org

http://www.libsdl.org/mailman/listinfo/sdl

End of Rant.

Jimmy
Jimmy’s World (http://www.jimmysworld.org)
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: This is a digitally signed message part
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020703/187a44c1/attachment.pgp

(Jimmy, can you please try to get your mail software to mark
quoted lines with '> ’ or something. It’s quite confusing
to see what looks like your own post, but with the "wrong"
sender! :slight_smile:

[…fixed logic frame rate…]

Ok, I’m basically sold on the idea… the only issue for me is that
logical frames will take place independently of visual frames (which is
good)… but since there isn’t timestamping of system events (even
though it would be nice), won’t there be control and logic
inconsistencies whenever a visual frame IS rendered because of the
likelyhood of missing a logic frame or two during a visual update?

Well, yes - but if that turns out to be a real problem, there’s
still the option of setting up your own thread that waits events,
and either timpstamps them and passes them on, or handles them
right away. I’d think the former is easier and more robust. Just
use an sfifo (http://olofson.net/mixed.html) or something.

Without the timestamp on the events, they’d bunch up during the visual
render.

Yeah.

I suppose this would be counteracted easily enough my capturing events
and queueing them, timestamped at the application level, during visual
updates.

Exactly.

Or by making the logical framerate low enough to ensure no
frames are skipped during a render.

No, that won’t work. “Skipping” logic frames is not an issue, except
for this event timing granularity thing. The only result will be a
very sluggish game, part because of the low logic frame rate, but
more importantly, since the logic->video frame rate interpolation
will add a whole logic frame of latency, regardless of video frame
rate. (Kobo Deluxe uses 33.33 Hz logic frame rate, and I’m starting
to think that’s too low…)

Is there a better way that I’m not seeing?

I don’t think so. It’s either using timestamps from the drivers (if
there are any), or using a thread somewhere to do the timestamping.
The latter could be done by SDL, but then you might as well do it
yourself. That said, SDL doing it would be more portable, and SDL
would only have to do it for targets without timestamped events.

AND
Would the events taking place slightly out of order really be
perceptable since they would have all happened between visual frames
anyway, and the difference in motion paths would likely be trivial.

It depends. A fixed latency is generally much less of a problem than
"random" jitter, although you can’t always tell the difference.

Taking an FPS as an example, if you spin around to fire a shotgun
at someone, you’ll have serious trouble actually hitting anything
if there’s too much of a random factor in the button->fire latency.

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn 03/07/2002 17:19:20 , Jimmy wrote:

On Wed, 2002-07-03 at 15:57, David Olofson wrote:

(Jimmy, can you please try to get your mail software to mark
quoted lines with '> ’ or something. It’s quite confusing
to see what looks like your own post, but with the "wrong"
sender! :slight_smile:

Sorry bout that :slight_smile:
The evolution does when the default is text mail and not html, but I had
to switch to html so I could send PGP signatures to Outlook since text
formatted messages with signatures get processed as perl by default on
Outlook Express on a couple friends machines. Explain that, by the way
:wink:
When it starts as html it just grays it, and the switch back to text
doesn’t add the '>'s and this is offtopic and I’m rambling and I’m going
to shut up. :slight_smile:

[…fixed logic frame rate…]

Ok, I’m basically sold on the idea… the only issue for me is that
logical frames will take place independently of visual frames (which is
good)… but since there isn’t timestamping of system events (even
though it would be nice), won’t there be control and logic
inconsistencies whenever a visual frame IS rendered because of the
likelyhood of missing a logic frame or two during a visual update?

Well, yes - but if that turns out to be a real problem, there’s
still the option of setting up your own thread that waits events,
and either timpstamps them and passes them on, or handles them
right away. I’d think the former is easier and more robust. Just
use an sfifo (http://olofson.net/mixed.html) or something.

Multithreading bad, Jimmy hates and will avoid until absolutely
necessary. Either way, I can interlace the rendering with picking up
the events and queueing them.

AND
Would the events taking place slightly out of order really be
perceptable since they would have all happened between visual frames
anyway, and the difference in motion paths would likely be trivial.

It depends. A fixed latency is generally much less of a problem than
"random" jitter, although you can’t always tell the difference.

Taking an FPS as an example, if you spin around to fire a shotgun
at someone, you’ll have serious trouble actually hitting anything
if there’s too much of a random factor in the button->fire latency.

Indeed.

Anyway, thanks for the insight.On Thu, 2002-07-04 at 10:07, David Olofson wrote:

On 03/07/2002 17:19:20 , Jimmy <@Jimmy> wrote:

On Wed, 2002-07-03 at 15:57, David Olofson wrote:

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology Real


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

End of Rant.

Jimmy
Jimmy’s World (http://www.jimmysworld.org)
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: This is a digitally signed message part
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020704/79757e92/attachment.pgp

[…]

Well, yes - but if that turns out to be a real problem, there’s
still the option of setting up your own thread that waits events,
and either timpstamps them and passes them on, or handles them
right away. I’d think the former is easier and more robust. Just
use an sfifo (http://olofson.net/mixed.html) or something.

Multithreading bad, Jimmy hates and will avoid until absolutely
necessary. Either way, I can interlace the rendering with picking up
the events and queueing them.

Urgh… I’d say an event thread and an sfifo is much cleaner than
interleaving/cooperative multitasking ever could be.

Also note that interleaving won’t work with indirect rendering
systems, such as OpenGL (and thus, glSDL). If you run a reasonably
fast 2D game on a h/w accelerated retrace syncing display, your
main loop will spend most of the time in SDL_Flip() waiting for the
retrace. That is, you won’t have the CPU more than a fraction of
each frame, so you’ll have practically the same event timing
issues as if you didn’t try to timestamp.

As for the issues with threading, the sfifo would take care of that
completely. You wouldn’t see more of the threading mess than if it
had been SDL or the OS doing the timestamping. Here’s about what
you’d have to do in the event thread:

while(1)
{
Uint32 timstamp;
SDL_Event ev;
if(SDL_WaitEvent(&ev) < 0)
break; /* Or some actual error handling… /
timestamp = SDL_GetTicks();
while(sfifo_space(&evfifo) < sizeof(timestamp) + siveof(ev))
SDL_Delay(10); /
This is an error condition! */
sfifo_write(&evfifo, &timestamp, sizeof(timestamp));
sfifo_write(&evfifo, &ev, sizeof(ev));
}

…and in your main thread, you just do something like this:

while(1)
{
Uint32 timstamp;
SDL_Event ev;
while(sfifo_used(&evfifo) >= sizeof(timestamp) + sizeof(ev))
{
sfifo_read(&evfifo, &timestamp, sizeof(timestamp));
sfifo_read(&evfifo, &ev, sizeof(ev));
advance_logic_time(timestamp);
/*
* Insert the usual SDL event handling here
*/
}
advance_logic_time(SDL_GetTicks());
render_frame();
}

Note that the sfifo (AFAIK) does not function as a time gate, so we
shouldn’t be getting events from the future. :wink: (Or: No, we don’t
have to check the timestamps!)

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn 04/07/2002 11:20:38 , Jimmy wrote:

[…]

Urgh… I’d say an event thread and an sfifo is much cleaner than
interleaving/cooperative multitasking ever could be.

Well, it’s always good to re-evaluate old decisions, I guess. :slight_smile:

Also note that interleaving won’t work with indirect rendering
systems, such as OpenGL (and thus, glSDL). If you run a reasonably
fast 2D game on a h/w accelerated retrace syncing display, your
main loop will spend most of the time in SDL_Flip() waiting for the
retrace. That is, you won’t have the CPU more than a fraction of
each frame, so you’ll have practically the same event timing
issues as if you didn’t try to timestamp.

Indeed

As for the issues with threading, the sfifo would take care of that
completely. You wouldn’t see more of the threading mess than if it
had been SDL or the OS doing the timestamping. Here’s about what

[…]

I’m just loath to add another layer into the event handling. I’ve
already converted the SDL events to mix with other in game events all in
pure C++, adding yet another layer of processing between SDL and the
native wrapping feels wrong somehow. And adding threading to the Event
scheme at the application level would require some serious rewriting
that I’m really not interested in doing.

Anyway, good suggestions/points all around. Thanks.On Thu, 2002-07-04 at 12:35, David Olofson wrote:

On 04/07/2002 11:20:38 , Jimmy <@Jimmy> wrote:

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology Real


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

End of Rant.

Jimmy
Jimmy’s World (http://www.jimmysworld.org)
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 232 bytes
Desc: This is a digitally signed message part
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20020705/f55dd9bd/attachment.pgp

[…]

I’m just loath to add another layer into the event handling. I’ve
already converted the SDL events to mix with other in game events all in
pure C++, adding yet another layer of processing between SDL and the
native wrapping feels wrong somehow.

Right, but that can’t be avoided without changind the SDL API and
adding timestamps to events.

And adding threading to the Event
scheme at the application level would require some serious rewriting
that I’m really not interested in doing.

Why? If you can use the SDL event system, there can’t be much more
to it than the example code I posted. If you can’t make use of the
timestamps, well, then need to redesign anyway, or just accept the
"video induced timing granularity". :slight_smile:

//David

.---------------------------------------
| David Olofson
| Programmer

david.olofson at reologica.se
Address:
REOLOGICA Instruments AB
Scheelev?gen 30
223 63 LUND
Sweden
---------------------------------------
Phone: 046-12 77 60
Fax: 046-12 50 57
Mobil:
E-mail: david.olofson at reologica.se
WWW: http://www.reologica.se

`-----> We Make Rheology RealOn 05/07/2002 11:10:22 , Jimmy wrote: