tags:

views:

1417

answers:

10
#include <stdio.h>

int main() {
  while(!DONE) {
    /* check for stuff */
  }
  return 0;
}

The above code sample uses 100% cpu until DONE is true. How can I implement a program that loops and only terminates when DONE, but which doesn't use 100% cpu? Modern languages use something like App.ProcessMessages or something like that to give the OS the control for the moment and then return to the loop.

I'm new at C, obviously... using latest GCC, linux and windows (a portable solution would be great!)

+3  A: 

use

Sleep(int milliSeconds)

Clox
The argument to sleep is actually a number of seconds, not milliseconds.
Tyler McHenry
I think it actually depends on the OS...while you're right about the parameter being seconds under Unix/Linux/*BSD, I think I remember it being milliseconds under Windows...It's been years though, so I could be wrong...
Nicolas
sleep() takes number of seconds. usleep() (BSD and POSIX) takes microseconds. nanosleep() (POSIX too) takes nanoseconds.
qrdl
Sleep should be a last resort, as it will wake the processor even if no work is to be done. This can kill power management on laptops and the like.
Ron Warholic
+2  A: 

What exactly are you checking for?

If you're checking something volatile that is changed by hardware or another process, just call sleep in your loop.

If you are waiting on a file descriptor or a network socket descriptor, you will want to use select or poll in your loop to wait for the descriptor to have data ready for consumption.

Tyler McHenry
A: 

Use yield().

samoz
This is not portable, since it is defined by neither the C standard nor POSIX.
Tyler McHenry
Wouldn't that just give other processes more time, still taking all the time other processes do not consume?
liori
A: 

If I'm guessing correctly (I don't know about it), the equivalent of App.ProcessMessages is doing blocking IO. And as I don't know of any implementation of C on multitasking OS which uses polling, any standard C IO should be safe.

AProgrammer
+3  A: 

Your two options would be polling, and some kind of event notification.

Polling would be easiest to program -- basically you have your thread sleep for a short while every pass through the loop. This releases the processor to other tasks. The downside is that there will be a delay in your "check for stuff" code -- so if you're sleeping for a second, it might be up to a second before your code detects the condition. Your code here will be easy to port.

The other option is to wait on a POSIX conditional, or Windows event or something like that. Not only will this code be changed, but then the "stuff you're checking" will need to trigger the flag to say it is done. This would be a little less portable code, although there are probably libraries to abstract away the platform. But you'll get immediate results to the event, and no wasted processor time checking for things that aren't there.

Clyde
+1 for suggesting use of POSIX synchronization.
Stephen C
+6  A: 

You have several choices:

  1. Use sleep() to force the process to suspend periodically and allow other process to use the CPU
  2. Run at a lower priority level - which will cause the OS to assign less CPU time
  3. Use a mutex or other synchronization object to detect when work is available - which will keep the process from consuming any CPU time unless it is actually doing work
  4. If you get work faster than you can process it - you may still need to use some sort of sleep/priority model to avoid completely consuming the CPU.

Option #2 can be tricky to do in a platform/OS neutral manner. Your best bet is to launch the process and change its priority in the runtime environment.

LBushkin
A: 

On windows, you can use Sleep(int milliseconds), defined on windows.h.

danielv
+7  A: 

It depends what you want to do inside this loop.

If you are waiting inside the loop (i.e. if keypressed { do something} then your mechanism will waste system resources giving nothing in return. A faster processor will just make more idle loops. This can be solved by waiting for events Not just sleep, but preferably an event which triggers that something meaningful can be done. For instance, a file operation (stdin is also a file) would be a portable mechanism. This will give way to other applications until data is available. When you become more specific it may be required to dive into semaphores or signals which are often OS dependent. An abstraction layer can resolve this.

If you are doing something useful (i.e. processing a lot of data), then 100% cpu load just means that the processor is used in the most efficient way. You can rely on the operating system to give way to other and possibly higher priority tasks.

Using a function like sleep will lower cpu usage, but your application will be slower. It will require to get a tradeoff between acceptable performance and cpu load. The maximum execution speed will be defined by your sleep parameter, and no longer by the cpu speed. Also, if power is a concern (i.e. battery life time), then this will require the cpu to wakeup (end of sleep period) with no work to be done; i.e. a different waste of system resources.

Adriaan
I guess I'll have to learn the semaphores and signals thenAny specific pointers on that? :)
pwseo
What kind of processing is inside the main loop? Messages, signals, semaphores are more related to the operating system thant he underlying language. For instance, http://www.ibm.com/developerworks/eserver/library/es-win32linux-sem.html shows how semaphores are handled in windows versus linux. If you need to support both, you may either use POSIX (which is optional for windows, i.e. in cygwin) or put the code in a platform-dependent module which you create for each OS.
Adriaan
A: 

If I understood right, you said in the comments that DONE can be changed from other threads. If so, condition variables make sense. With pthreads, one would do:

In the thread that waits:

pthread_mutex_lock(&mutex);
while (!DONE) {
     pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);

In other threads, when DONE is changed:

pthread_mutex_lock(&mutex);
DONE = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
tsg
A: 

Sleep(0); is enough

Arabcoder