In the past time I read much about loops consuming full cpu times vs. others. Can someone explain the difference between both and give an example, which can be understood??
Actually theres is no necessity consuming more cpu time than the program requires.
Let's assume your program does 100 frames per second. Wallow in simplicity.
Now the OS also has its own timers. If it runs though all the programs in the list and it has time left over, it puts the CPU itself to sleep, only to be awakened by a hardware timer chip, then it runs through all the programs, giving them some small sliver of CPU time as requested. But if your program is in a sleep(), and doesn't need any time, it just skips over it to the next program, which enables it to put the CPU into halt mode (sleep) that much sooner, resulting in lower temperatures and electrical usage.
[EDIT]
I should have stated that last a little more clearly. If 50 programs are running, and none of them want to sleep(), then each one will get 1/50th of an OS tick. If 49 of them want to sleep(), then the last remaining program will get the entire time slice, resulting in 100% CPU for that program. Only if they all ask for some sleep() time will CPU usage be less than 100%. Disk access and other things that block may do this as well as sleep().
Another explanation. In a multitasking operating system, each process/thread is in a certain state (http://en.wikipedia.org/wiki/Process_state). In the 'Waiting' state the OS will give a share of the available CPU time to your thread, moving it to the 'Running' state. Once that time slice is exhausted (e.g. 10 ms), the thread moves back into the 'Waiting' state, and another process/thread is allowed to execute.
while (!key[KEY_ESC]) { /* do nothing */ }
This is called a busy wait. Without any other information, you are asking the OS to give you as much CPU time as possible. Yet during that time all you are doing is checking if a global variable was changed - in this case by a Allegro 4 background thread, which could only change the global variable once it gets a chance to execute. It won't be able to execute on the same core while you are occupying it either, so very inefficient.
For better use of the CPU, you need to put the process/thread into the 'Blocked' state until you can make progress. An imperfect way to do that is to give up the rest of your time slice and not execute again until some amount of time has passed. This can be done, for example, with Allegro's rest and al_rest calls.
This is imperfect because your thread still has to be run every so often to check a global variable, probably somewhere between 100 and 1000 times per second. At least you are no longer busy waiting, but not as good as it could be.
The better solution is to put your thread into the 'Blocked' state for as long as possible, but no longer, otherwise you will react too slowly when something does change. Various function calls will do this. In Allegro 5 the principal call which does so is al_wait_for_event. Your thread will be 'Blocked' and only be run again until there is something in the event queue:
while (!quit) { al_wait_for_event(queue, &ev); /* thread blocks until queue is non-empty */ if (ev.type == ALLEGRO_EVENT_KEY_DOWN && ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { quit = true; } }
"All Hail!"
I feel enlightened now.