Sign in to follow this  

Sleep() Question

This topic is 4864 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

using C++ && Direct3D How do you achieve a constant frame rate in a game? I've seen the use of this Sleep( int ) method, but I'm a bit skeptical of it. Why? Well, you have all this code, lines upon lines, and then you have this sleep( SomeConst_int_Here ); statement. Supposedly, it makes the game speed dependent on this constant frame rate, not the speed of your processor. But... How does the compiler interpret this message? Lets say you have this code: while( !game.over() ) { FunctionA(); sleep( x ); // assume x is int of some sort FunctionB() } OK, so what does the compiler do? Does it... A. 1. execute FunctionA() 2. wait x milliseconds before continuing 3. execute FunctionB() 4. goto 1 B. 1. execute FunctionA() 2. read the sleep statement, keep it in mind, but don't wait 3. execute FunctionB() 4. execute FunctionA() 5. make sure that x milliseconds passed since last execution of sleep, if not, pause all execution 6. goto 2 C. Other (explain) All help appreciated in advance

Share this post


Link to post
Share on other sites
Sleep() doesn't guarantee a constant frame rate at all. Sleep() suspends execution of a thread for at least the amount of time specified as its parameter (in milliseconds). It may actually suspend for longer.

Sleep(0), however, simply yields the remainder of the application's timeslice to the next equal priority thread or process. If there is none, it returns immediately. It's generally a good idea to have at least one call to Sleep(0) in a main or loop that calls no other wait functions simply because it makes preemption less necessary.

For PC games, fixed frame rates are generally overrated. It's usually far more robust to make your simulation frame rate independent. However, if you are insistent on maintaining a fixed frame rate, then you're going to have to perform a fair amount of manually timing, etc.

  1. Maintain last draw time, tLast.

  2. Measure interval between current time and tLast. If greater than or equal to drawInterval, draw and set tLast to current time.

    If less that tLast, Sleep(0).

  3. Wash, rinse, repeat.

Share this post


Link to post
Share on other sites
A.

Btw, the compiler isn't what makes it sleep. Sleep is a function provided by the OS which tells the scheduler to suspsend the current thread for X milliseconds.

Beware however, it is likely that it won't sleep exactly as long as you specified, depending on the granularity of the system timer and various other reasons. For example Sleep(1) is usually around 11 miliseconds on XP, etc. So you can't really rely on it.

An alternative is to just do an empty loop while you're waiting, like this:

void MySleep( double seconds )
{
double start = MyHighPrecisionClock();
while( MyHighPrecisionClock() - start < seconds );
}


This is much more reliable but of it course will make your program use 100% cpu power, unlike Sleep(). But that's usually not important for games anyways.

Edit: Beat to the punch, but perhaps still useful. Need to type/Think faster :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Oluseyi
...
Sleep(0), however, simply yields the remainder of the application's timeslice to the next equal priority thread or process. If there is none, it returns immediately. It's generally a good idea to have at least one call to Sleep(0) in a main or loop that calls no other wait functions simply because it makes preemption less necessary.
...


Sorry, could you (or anyone, really) explain that paragraph a bit better? Sounds helpful, but I don't know what you mean!

Share this post


Link to post
Share on other sites
"sleep" talks to the operating system. All the compiler does is translate something you find readable into something the OS finds readable. :)

The operating system runs several processes; each may have one or more thread. If you are writing multithreaded code (not including threads created for you by a library that you link in), you will probably want to make sure you know how to sleep a single thread vs. the whole process. (I *think* this is the sleep() vs. Sleep() distinction on Windows. But check MSDN.) Anyway. What the system call does is take the current process out of the running (save a bunch of values from the computer's registers, basically, and then load them for a new thread/process), and put it (well, a struct describing it) into a "waiting list" to run again. The position in that list depends on the specified amount of sleep time, the other things that are running, *their* suspend conditions, etc.)

Then, in a PMT (pre-emptive multi-tasking) system, every so often the OS will have its *own* thread which runs, checks to see what waiting threads are now eligible to run, picks one, and starts it (forcibly interrupting whatever was already running). Under CMT (cooperative multi-tasking), whatever thread is running gets to continue doing so until it is polite enough to "stand down". (This is the model of multitasking that was used by old versions of MacOS; it hung around until after Windows had implemented PMT, and then got criticized - but it was certainly better than what older versions of Windows and DOS offered.) Of course, even PMT may not be able to interrupt a "tight loop".

That's skipping quite a few details and losing a fair bit of accuracy in the name of understandability; I'm also not really an authority on this stuff (I studied it in university, but that's nothing special really).

Share this post


Link to post
Share on other sites
Building on the previous post:

Quote:
Original post by v0dKA
Quote:
Original post by Oluseyi
...
Sleep(0), however, simply yields the remainder of the application's timeslice to the next equal priority thread or process. If there is none, it returns immediately. It's generally a good idea to have at least one call to Sleep(0) in a main or loop that calls no other wait functions simply because it makes preemption less necessary.
...


Sorry, could you (or anyone, really) explain that paragraph a bit better? Sounds helpful, but I don't know what you mean!


"Sleep(0)", by extension of how Sleep() works in general, means "stop executing now, and do not execute for at least zero more milliseconds". Which is to say, "stop executing me so something else can have a chance, but I'm good to go again at any time."

If you don't do this, or provide some other "wait function" with the same effect*, then the operating system has to forcibly tell your thread/process to stop, i.e. "preempt" it. On some older systems (you probably won't find many of them in the wild any more though, unless you work on Big Iron(TM) perhaps) this facility is not available. Even where it is, you don't really want to rely on it if you don't have to (although I'm not entirely sure why).

* Doing most console or file I/O operations will be good enough. Any time you hear the term "blocking I/O", this is what they're talking about: the current thread cannot proceed until there is more data available. For consistency, even if it is available, the thread will generally 'yield'.

Share this post


Link to post
Share on other sites

This topic is 4864 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this