Timing issues - SDL_Delay

I’m having some trouble with SDL_Delay. I’m trying to limit framerate for a
little tech-demo practice thing I’m doing. Now, this works perfectly:==============
while (fps.stop() < ( 1000 / FPS ) ){ //fps.stop() being part of my timer
//wait // class it returns the enlapsed time
} //between start() and stop().

Of course, this uses up all the CPU time available and skips when anything
else happens. None of which are acceptable. So I used this instead:

==============
time = 33 - fps.stop(); //Time being Uint32
if ( time > 0 ){
SDL_Delay( time );
}

This is when it all breaks down. The delay has a very unpredictable behaviour.
It starts working just fine and with no speed variations… then the animation
just stops and none of the events respond. Clearly stuck in the delay function.

So what gives? Am I doing anything wrong?

Heres the whole code from the modified version (SDL_Delay one)
http://pastebin.com/m3719631

Thanks

CptAJ <antonioetayo gmail.com> writes:

==============
time = 33 - fps.stop(); //Time being Uint32
if ( time > 0 ){
SDL_Delay( time );
}

Correct me if I’m wrong, but if time is an unsigned int (which is what Uint32 is)
then won’t 33-fps.stop() always be above zero if the frame doesn’t take exactly
33ms? So if your frame takes just slightly longer than the 33ms, you’ll be
waiting a looooong time for the next frame…

Either use a signed int or cast time to a signed quantity in your comparison
(the first method I think is far preferable!).

Something that might help to enhance your timer, too. Since you’ve got an object
as a timer module, you could also track the average frame rate, too, fairly
easily. That way, if you’ve got a couple of frames that take a long time to draw,
the delay for the next frame could be shortened a bit.

-J

Quite right, my friend. I guess I figured that since the program was so very
simple there wouldn’t be any problems with that. Murphy’s law once again…

Making time an int certainly fixed the problem. I didn’t know I could use an
int since the SDL docs said SDL_Delay takes an Uint32. I guess the conditional
was pretty silly too given that its unsigned =/

So what is it that happens, the substraction comes back negative and the Uint32
takes on a “random” value as a result?

Thanks for the help bro.

CptAJ <antonioetayo gmail.com> writes:

Quite right, my friend. I guess I figured that since the program was so very
simple there wouldn’t be any problems with that. Murphy’s law once again…

Making time an int certainly fixed the problem. I didn’t know I could use an
int since the SDL docs said SDL_Delay takes an Uint32. I guess the conditional
was pretty silly too given that its unsigned =/

So what is it that happens, the substraction comes back negative and the Uint32
takes on a “random” value as a result?

Thanks for the help bro.

An unsigned int takes a value between 0 and 2^N-1, whereas a signed int (int
is signed by default, so you don’t need the keyword) is -2^(N-1) through to
2^(N-2). Let’s say your system has 16-bit ints, that means unsigned is from 0 to
65535 (2^16 being 65536) and a signed int is -32768 to 32767.

The unsigned is purely a way of interpreting the number: the most significant bit
becomes the sign bit in a signed integer. Whenever it is 1, the number is assumed
to be negative. Whenever it is 0, the number is assumed to be positive. So, your
signed math 33-fps.stop() is working OK, but then the significance of the sign is
eliminated by assigning the result to an unsigned number. Likewise, the >
operation is perfectly valid for unsigned ints, it just is a complicated way of
asking if the value is non-zero. When you do a > on signed ints, however, the
sign bit is what is checked first: if it is set, the answer is false.

Does this make sense?

Glad you got it working!

-J

Yeah, it does.
Glad you were here to figure this thing out for me, mate. :wink:

AFAIK, Uint32 is just a typedef of an unsigned int (or long? I forgot). So
if you use a signed int (or the typedefed Sint32) to store the result of
Uint32, it will be casted to a signed int. And for the result in Uint32 if
it’s a negative value, it will be the max unsigned int value minus the
negative value. So -10 signed int is equal to 4,294,967,295 - 10 =
4,294,967,285 in unsigned int. CMIIW.

CptAJ said:

Quite right, my friend. I guess I figured that since the program was so
very
simple there wouldn’t be any problems with that. Murphy’s law once
again…

Making time an int certainly fixed the problem. I didn’t know I could use
an
int since the SDL docs said SDL_Delay takes an Uint32. I guess the
conditional
was pretty silly too given that its unsigned =/

So what is it that happens, the substraction comes back negative and the
Uint32
takes on a “random” value as a result?

Thanks for the help bro.


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

Fare thee well,
Bawenang R. P. P.----------------
ERROR: Brain not found. Please insert a new brain!

?Do nothing which is of no use.? - Miyamoto Musashi.

“I live for my dream. And my dream is to live my life to the fullest.”

Ahah! Thats it then. That clearly explains the extended delay.

CptAJ <antonioetayo gmail.com> writes:

==============
time = 33 - fps.stop(); //Time being Uint32
if ( time > 0 ){
SDL_Delay( time );
}

Correct me if I’m wrong, but if time is an unsigned int (which is what Uint32 is)
then won’t 33-fps.stop() always be above zero if the frame doesn’t take exactly
33ms? So if your frame takes just slightly longer than the 33ms, you’ll be
waiting a looooong time for the next frame…

Either use a signed int or cast time to a signed quantity in your comparison
(the first method I think is far preferable!).

Neither of which are particularly ideal, actually, because they cause
unnecessary conversion work. Just rearrange the code:

if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}

Casting to signed ints not only requires extra conversion, but it also
still results in incorrect logic in many cases (albeit, not this one).
It’s a really bad habit to get into. If you don’t explicitly need a
negative value in your calculation, then it’s guaranteed that there is a
way to get what you want without using signed ints and without hitting
overflow issues.On Wed, 2007-07-18 at 03:40 +0000, Jason wrote:

Something that might help to enhance your timer, too. Since you’ve got an object
as a timer module, you could also track the average frame rate, too, fairly
easily. That way, if you’ve got a couple of frames that take a long time to draw,
the delay for the next frame could be shortened a bit.

-J


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

Sean Middleditch <@Sean_Middleditch>

Well, to be more efficient again, wouldn’t it be better if the result of
fps.stop() be stored in a temporary variable? Because in this one,
fps.stop() is called twice. And if this function is a big one, then
there’s a whole lot extra unnecessary processes.

so maybe this will do:

Uint32 temp=fps.stop();
if (temp < 33) {
SDL_Delay(33 - temp);
}

Sean Middleditch said:

Neither of which are particularly ideal, actually, because they cause
unnecessary conversion work. Just rearrange the code:

if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}

Casting to signed ints not only requires extra conversion, but it also
still results in incorrect logic in many cases (albeit, not this one).
It’s a really bad habit to get into. If you don’t explicitly need a
negative value in your calculation, then it’s guaranteed that there is a
way to get what you want without using signed ints and without hitting
overflow issues.

Sean Middleditch


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

Fare thee well,
Bawenang R. P. P.----------------
ERROR: Brain not found. Please insert a new brain!

?Do nothing which is of no use.? - Miyamoto Musashi.

“I live for my dream. And my dream is to live my life to the fullest.”

Well, to be more efficient again, wouldn’t it be better if the result
of
fps.stop() be stored in a temporary variable? Because in this one,
fps.stop() is called twice. And if this function is a big one, then
there’s a whole lot extra unnecessary processes.

Not to mention, fps.stop() might not return the same value for the two
calls. It’s implementation might be as simple as

return startTime - SDL_GetTicks();

So this code

if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}

would have a potential lock. If the first call returned say, 32, then
the OS decided to do something else for 2ms so the second call returns
34. Then the delay would be very big again.

so maybe this will do:

Uint32 temp=fps.stop();
if (temp < 33) {
SDL_Delay(33 - temp);
}

I’ll vote for this solution, as it assumes the least about
implementation of fps.–
Jukka-Pekka Manninen

Well, to be more efficient again, wouldn’t it be better if the result of
fps.stop() be stored in a temporary variable? Because in this one,
fps.stop() is called twice. And if this function is a big one, then
there’s a whole lot extra unnecessary processes.

True enough. I assumed it was something with a body as simple as
{ return ticks; } that might be optimized away, but you’re definitely
right. If the function has side effects or returns inconsistent results
between consecutive calls, a temp value is pretty vital.On Thu, 2007-07-19 at 10:07 +0700, benang at cs.its.ac.id wrote:

so maybe this will do:

Uint32 temp=fps.stop();
if (temp < 33) {
SDL_Delay(33 - temp);
}

Sean Middleditch said:

Neither of which are particularly ideal, actually, because they cause
unnecessary conversion work. Just rearrange the code:

if (fps.stop() < 33) {
SDL_Delay(33 - fps.stop());
}

Casting to signed ints not only requires extra conversion, but it also
still results in incorrect logic in many cases (albeit, not this one).
It’s a really bad habit to get into. If you don’t explicitly need a
negative value in your calculation, then it’s guaranteed that there is a
way to get what you want without using signed ints and without hitting
overflow issues.

Sean Middleditch <@Sean_Middleditch>


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

Fare thee well,
Bawenang R. P. P.


ERROR: Brain not found. Please insert a new brain!

?Do nothing which is of no use.? - Miyamoto Musashi.

“I live for my dream. And my dream is to live my life to the fullest.”


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

Sean Middleditch <@Sean_Middleditch>