Waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1) fixes
that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?–
Chris Thielen <@Christopher_Thielen>

In your timer callback use SDL_PushEvent() to unblock the SDL_WaitEvent()
call.

Dan.> ----- Original Message -----

From: chris@luethy.net (Christopher Thielen)
To:
Sent: Thursday, November 07, 2002 7:47 PM
Subject: [SDL] waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1) fixes
that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?


Chris Thielen


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

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?On Thu, 2002-11-07 at 19:41, Daniel Goertzen wrote:

In your timer callback use SDL_PushEvent() to unblock the SDL_WaitEvent()
call.

Dan.

----- Original Message -----
From: “Chris Thielen” <@Christopher_Thielen>
To:
Sent: Thursday, November 07, 2002 7:47 PM
Subject: [SDL] waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1) fixes
that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?


Chris Thielen <@Christopher_Thielen>


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


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

Chris Thielen <@Christopher_Thielen>

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?

Use a different timer to push the event.

	Bob PendletonOn Fri, 2002-11-08 at 09:10, Chris Thielen wrote:

On Thu, 2002-11-07 at 19:41, Daniel Goertzen wrote:

In your timer callback use SDL_PushEvent() to unblock the SDL_WaitEvent()
call.

Dan.

----- Original Message -----
From: “Chris Thielen”
To:
Sent: Thursday, November 07, 2002 7:47 PM
Subject: [SDL] waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1) fixes
that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?


Chris Thielen


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


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

Chris Thielen


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

±-----------------------------------+

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?

Use a different timer to push the event.

it wouldn’t matter. the code literally goes:

SDL_WaitEvent()
Check for timer event, if so, callback (for all timers)
repeat

the problem is waitevent() holds up the code and pollevent() is cpu
intensive, whereas pollevent() with sdl_delay() is too sluggish, even on
a one millisecond delay.

so another timer would still have to wait for SDL_WaitEvent(). is a
multithreaded app the only way to do this?On Fri, 2002-11-08 at 10:19, Bob Pendleton wrote:

On Fri, 2002-11-08 at 09:10, Chris Thielen wrote:

On Thu, 2002-11-07 at 19:41, Daniel Goertzen wrote:

In your timer callback use SDL_PushEvent() to unblock the SDL_WaitEvent()
call.

Dan.

----- Original Message -----
From: “Chris Thielen” <@Christopher_Thielen>
To:
Sent: Thursday, November 07, 2002 7:47 PM
Subject: [SDL] waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1) fixes
that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?


Chris Thielen <@Christopher_Thielen>


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


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

Chris Thielen <@Christopher_Thielen>


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

Chris Thielen <@Christopher_Thielen>

No, it does work. You send an event FROM the timer callback. That
event causes WaitEvent to return. The code for the callback looks like:

Uint32 timerCallback(Uint32 interval, void *param)
{
SDL_Event event;

event.type = SDL_USEREVENT;
event.user.code = MY_TIMEREVENT;
event.user.data1 = (void *)SDL_GetTicks();
event.user.data2 = (void *)0;

SDL_PushEvent(&event);

return interval;
}

The event is generated in the timer thread, not in the main thread. Think
about it.

	Bob PendletonOn Fri, 2002-11-08 at 17:40, Chris Thielen wrote:

On Fri, 2002-11-08 at 10:19, Bob Pendleton wrote:

On Fri, 2002-11-08 at 09:10, Chris Thielen wrote:

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?

Use a different timer to push the event.

it wouldn’t matter. the code literally goes:

SDL_WaitEvent()
Check for timer event, if so, callback (for all timers)
repeat


±-----------------------------------+

ah, there’s the misunderstanding. the program isnt multithreaded at all.
the timers are my own c code and everything runs on one thread. the
"timer callbacks" are all my code, and SDL_WaitEvent() is just used to
receieve events. so then, multithreading is the only way to go? i
dunno, is that how most games do input?On Fri, 2002-11-08 at 18:55, Bob Pendleton wrote:

On Fri, 2002-11-08 at 17:40, Chris Thielen wrote:

On Fri, 2002-11-08 at 10:19, Bob Pendleton wrote:

On Fri, 2002-11-08 at 09:10, Chris Thielen wrote:

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?

Use a different timer to push the event.

it wouldn’t matter. the code literally goes:

SDL_WaitEvent()
Check for timer event, if so, callback (for all timers)
repeat

No, it does work. You send an event FROM the timer callback. That
event causes WaitEvent to return. The code for the callback looks like:

Uint32 timerCallback(Uint32 interval, void *param)
{
SDL_Event event;

event.type = SDL_USEREVENT;
event.user.code = MY_TIMEREVENT;
event.user.data1 = (void *)SDL_GetTicks();
event.user.data2 = (void *)0;

SDL_PushEvent(&event);

return interval;
}

The event is generated in the timer thread, not in the main thread. Think
about it.


Chris Thielen <@Christopher_Thielen>

No, it does work. You send an event FROM the timer callback.

ah, there’s the misunderstanding. the program isnt multithreaded
at all.

As far as I understood this discussion, it does not matter whether
you send the event from another thread, or from the event handler.
All that matters is that the event ends up in the queue, and when
execution reaches WaitEvent, it will see that event and process it.

i dunno, is that how most games do input?

It looks to me you are doing things way too complicated. Here is a
typical game loop:

while (!finished)
{
handle_events()
update_game_world()
draw_screen()
wait_for_next_frame()
SDL_Flip()
}

Every time through the loop you first handle the events:

while (SDL_PollEvent(&event))
{
    switch (event.type)
    {
        case SDL_KEYDOWN: ...
    }
}

Then you update the state of the game world, such as positions of
your sprites, collision detection, etc. You can do some of this
straight from your event handlers, too, if you want. After the game
world has updated, you draw the visible parts of the game world on
the screen.

I am assuming here you want a fixed framerate, of say, 50 fps. That
means that the loop runs every 20ms. If the game logic takes less
than that, you have some time to spare. To keep the framerate
constant, we use wait_for_next_frame(). The function looks like
this:

 int32 left = next_frame_time - SDL_GetTicks();
 if (left > 10) { SDL_Delay((left/10)*10 - 1); }
 while (SDL_GetTicks() < next_frame_time) { }
 next_frame_time += MILLISECS_PER_FRAME;

Here, next_frame_time is when the next frame is supposed to happen,
which is 20ms from now (the value of MILLISECS_PER_FRAME). If there
are more than 10ms of unused time left in the current frame, we wait
with SDL_Delay(), which frees up time for other processes. We wait
out the remainder in a busy loop. This is necessary because
SDL_Delay() typically has a granularity of 10ms, so even if you say
SDL_Delay(1) you will wake up 10ms later, not 1.

And that is it… There are other ways to do things, but this
approach is probably the simplest. The example above is not
complete – it does not handle pauzing of the game, or frames that
take more than 20ms to complete – but it should get you started ;-)–
Matthijs Hollemans
All Your Software
www.allyoursoftware.com

Hi Chris. I think subsequent replies have hinted at the answer but I’ll
rehash.

When you create a timer it will generally run in a separate thread, so you
WILL be able to call SDL_PushEvent from your callback while your main thread
is blocked on SDL_WaitEvent. So effectively your program is multithreaded
without you really intending it. You seem keen to avoid multithreading
which is fine because it is very easy to shoot yourself in the foot. You
have to be careful what you do in your callback, and the safest thing to do
is just queue an event with SDL_PushEvent and let the main thread do the
work.

Now, did you just assume that your callback would not operate while blocked
on SDL_WaitEvent, or did you actually observe this behaviour? I took a
quick look at the SDL source code and both Linux and Windows use threaded
timers… there is no choice in this matter There does appear to be an
option to use non-threaded timers on some platforms which could cause you
problems, but I’m betting you’re on Linux, Windows, or some other threaded
timer platform.

Hope I’ve set you straight.

Cheers,
Dan.> ----- Original Message -----

From: chris@luethy.net (Christopher Thielen)
To:
Sent: Friday, November 08, 2002 9:10 AM
Subject: Re: [SDL] waiting for events and callbacks

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?

On Thu, 2002-11-07 at 19:41, Daniel Goertzen wrote:

In your timer callback use SDL_PushEvent() to unblock the
SDL_WaitEvent()

call.

Dan.

----- Original Message -----
From: “Chris Thielen”
To:
Sent: Thursday, November 07, 2002 7:47 PM
Subject: [SDL] waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1)
fixes

that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?


Chris Thielen


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


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

Chris Thielen


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

Hrm, so coming from all these replies (which I thank all you guys,
thanks Daniel, Bob, and Matthijs), I should probably just switch my
timer code to SDL timers? The problem is I have not been using SDL
timers, I have been keeping the time myself and checking timers and
doing the callbacks myself. I’ll look into SDL timers instead, and sorry
for that threading confusion.On Sat, 2002-11-09 at 10:35, Daniel Goertzen wrote:

Hi Chris. I think subsequent replies have hinted at the answer but I’ll
rehash.

When you create a timer it will generally run in a separate thread, so you
WILL be able to call SDL_PushEvent from your callback while your main thread
is blocked on SDL_WaitEvent. So effectively your program is multithreaded
without you really intending it. You seem keen to avoid multithreading
which is fine because it is very easy to shoot yourself in the foot. You
have to be careful what you do in your callback, and the safest thing to do
is just queue an event with SDL_PushEvent and let the main thread do the
work.

Now, did you just assume that your callback would not operate while blocked
on SDL_WaitEvent, or did you actually observe this behaviour? I took a
quick look at the SDL source code and both Linux and Windows use threaded
timers… there is no choice in this matter There does appear to be an
option to use non-threaded timers on some platforms which could cause you
problems, but I’m betting you’re on Linux, Windows, or some other threaded
timer platform.

Hope I’ve set you straight.

Cheers,
Dan.

----- Original Message -----
From: “Chris Thielen” <@Christopher_Thielen>
To:
Sent: Friday, November 08, 2002 9:10 AM
Subject: Re: [SDL] waiting for events and callbacks

If I use SDL_PushEvent() while SDL_WaitEvent() is called, then
SDL_WaitEvent() will return and produce the desired effect, however, how
do I call SDL_PushEvent() while SDL_WaitEvent() is running? It’s not
multithreaded, and the timer callback is only called after
SDL_WaitEvent() is returned, so that would only push the event after the
program has halted for too long on SDL_WaitEvent(). Should the program
be multithreaded or am I misunderstanding what you’ve said?

On Thu, 2002-11-07 at 19:41, Daniel Goertzen wrote:

In your timer callback use SDL_PushEvent() to unblock the
SDL_WaitEvent()

call.

Dan.

----- Original Message -----
From: “Chris Thielen” <@Christopher_Thielen>
To:
Sent: Thursday, November 07, 2002 7:47 PM
Subject: [SDL] waiting for events and callbacks

Hello,
I have a problem and I was wondering if anybody could offer
suggestions. I have a simple user interface that uses SDL to draw and
get events. The interface uses callbacks, including callbacks for
timers, so say, every 35 ms, it’ll issue a callback. The problem is,
with SDL_PollEvent(), cpu is sucked up (and adding a SDL_Delay(1)
fixes

that problem but makes input response far too sluggish) but with
SDL_WaitEvent(), an event has to occur before SDL_WaitEvent() returns
and my code checks for timer callbacks … so timers are thrown off.
Any suggestions as to how I can keep cpu usage down, keep input
response fast, and issue the callbacks when I need?


Chris Thielen <@Christopher_Thielen>


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


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

Chris Thielen <@Christopher_Thielen>


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


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

Chris Thielen <@Christopher_Thielen>

S’ok. no problem. YES, you should just use SDL timers. They work. The
timer code in SDL is very good and very reliable.

	Bob PendletonOn Sat, 2002-11-09 at 13:41, Chris Thielen wrote:

Hrm, so coming from all these replies (which I thank all you guys,
thanks Daniel, Bob, and Matthijs), I should probably just switch my
timer code to SDL timers? The problem is I have not been using SDL
timers, I have been keeping the time myself and checking timers and
doing the callbacks myself. I’ll look into SDL timers instead, and sorry
for that threading confusion.

±-----------------------------------+