Programming question about "input/game" loop

Hi,

I'm studying programming and there's something I'm wondering about. Many tutorials and books demonstrate a loop like this:
Code:
while (!condition)
    { ... }

For example in a game it is for checking if a quit flag is set, by the user entering "q" or some such.

Then, recently I wrote a little C++ program using the SDL library, which has that main "game loop" which polls over and over to see if an exit command was sent (e.g. by closing the window, or pressing alt+F4). I realized that it is using 100% CPU. Even just executing an empty infinite loop in C/C++ does the same.

Now, my questions:
  1. Is that a bad thing to do?
  2. Does production code have loops like that? Do actual finished video games have a main loop like that? If so, does it affect performance to become worse? I remember reading text from different places that says "the logic of all games depends on a kind of loop like that, which checks forever for quit conditions", and now it seems strange why would we do that if it eats 100% CPU.
  3. How to solve it?

Edit:
I've looked at the Angband code quickly. From main() it calls play_game(), which looks like this: (the ellipses are snipped lines. I only copied the ones which have "break")
Code:
while (TRUE)
{
    ...
    /* Handle "quit and save" */
    if (!p_ptr->playing && !p_ptr->is_dead) break;
    ...
    /* Handle "death" */
    if (p_ptr->is_dead) break;
    ...
}

So it does have an infinite loop. But it doesn't eat 100% CPU, most I've seen from top is 1%. Now I'm wondering, how is Angband's infinite loop different from my infinite loops which eat 100% CPU? It isn't immediately obvious to me what the difference is. I'll read more from Angband code, it looks really neat and clean.

If someone knows then please tell me.
 
1. Is that a bad thing to do?
As you might have already guessed, yes. This is called polling and it's usually a terrible thing to do.

Talvikuutamo said:
3. How to solve it?
You either wait for input or let the process sleep for a short time. Note that wait for input does not mean you constantly poll to see if there's input, but tell the kernel to wake you up as soon as there's input for your process (SDL_PollEvent vs SDL_WaitEvent).
 
This is often called busy waiting. Polling itself is not a problem, it's polling continuously at a high rate that is bad.
 
Usually with SDL, you call SDL_Sleep to wait off the remaining time per frame so it does not utilize 100% of the CPU and keeps to below 60 fps (for fast machines) whilst at the same time you work out the amount of time taken per frame to generate a time delta so you can use this for framerate independent animation.

What I notice with OpenGL however is that as the graphics card is doing processing, i.e in the glDrawArrays function the CPU waits in a sleep state which actually brings down the CPU usage on machines with weaker graphics cards (which take longer over the processing so the CPU is in wait mode for longer).

I think why Angband does not use 100% CPU is because as it uses curses, it probably blocks on the getch() function.
 
I believe that last example involves using a new thread. Threading is rarely necessary in games for timing events since it confuses matters. Especially since the whole game world and everything in it would effectively be a shared state and cause issues when the two threads try to access at the same time.

At work, we often use a system like...

Code:
float shootTimeout = 0.0f;

void onUpdate()
{
  shootTimeout += getEnvironment()->getTimeDelta();

  if(shootTimeout >= 3.0f)
  {
    shoot();
    shootTimeout = 0.0f;
  }
}

This means that shoot() will be called every 3 seconds.

Due to a limitation in JavaScript (and the fact that it is impossible to sleep) there are many workarounds using timers and other asynchronous types of things. Some people may prefer this type of architecture.
 
Back
Top