views:

148

answers:

6

Hello everybody. I want to run an infinite loop for a while. Basically, i want to have something like this

//do something

while(1){
  //do some work
}

//do some other thing

but i want the running time of the loop to be fixed, example, the loop could be running for 5 seconds. Do somebody have an idea?

+8  A: 

Just do sleep(5) (include unistd.h). You can use it like this:

// do some work here
someFunction();    

// have a rest
sleep(5);

// do some more work
anotherFunction();

If you're doing work inside the loop, you can do (include time.h):

// set the end time to the current time plus 5 seconds
time_t endTime = time(NULL) + 5;

while (time(NULL) < endTime)
{
    // do work here.
}
dreamlax
Keep in mind that the `while` loop will take *at least* 5 seconds, it may take longer than 5 seconds if the work inside the loop takes a long time.
dreamlax
this is interesting, but i don't want to make a system call inside thee loop
the_drug
@the_drug: Is there a reason why?
dreamlax
yes, beacause i am trying to measure the memory bandwidht. A system call will increase the execution time of the loop...
the_drug
+9  A: 

Try using clock().

#include <time.h>

clock_t start = clock();

while (1)
{
    clock_t now = clock();
    if ((now - start)/CLOCKS_PER_SEC > 5)
        break;

    // Do something
}
Jeff Dege
`clock()` returns the amount of processor time used, not real time.
dreamlax
A: 

Pseudo-code:

starttime = ...;

while(currentTime - startTime < 5){

}
Rin
A: 

Not tested; resolution is very coarse.

#include <time.h>
#define RUNTIME 5.0 /* seconds */

double runtime = 0;
double start = clock(); /* automatically convert clock_t to double */
while (runtime < RUNTIME / CLOCKS_PER_SEC) {
    /* work */
    runtime = clock() - start;
}

If /* work */ takes more than 5 seconds, the loop will take more than 5 seconds.

If /* work */ takes 1.2 seconds, the loop will execute approximately 5 times for a total of 6 seconds

pmg
Just curious, why use a `double` and not `clock_t`?
dreamlax
Because `clock_t` is an "arithmetic type". There is no guarantee it can hold fractional values (for instance: 0.5) ... and I feel better using `double`s
pmg
Also, after perusing the relevant [spec](http://www.opengroup.org/onlinepubs/009695399/functions/clock.html) it appears that `clock()` will return the amount of processor time used, not real time.
dreamlax
+1  A: 

First of all, consider using the sleep function if possible. If you have to do actual work for a specified time period, which I find unlikely, the following ugly solution would work:

#include <signal.h>
int alarmed = 0;
void sigh(int signum) {
    alarmed = 1;
}
int main(void){
    /* ... */
    signal(SIGALRM, &sigh);
    alarm(5); // Alarm in 5 seconds
    while(!alarmed) {
        /* Do work */
    }
    /* ... */
}

A solution using time.h would also be possible, and perhaps simpler and/or more accurate, depending on context:

#include <time.h>
int main(void){
    /* ... */
    clock_t start = clock();
    while(clock() - start < 5 * CLOCKS_PER_SEC) {
        /* Do work */
    }
    /* ... */
}
You
That should be `void sigh(int signum)`, right?
Oli Charlesworth
the first solution is the one i am actually using. The fact is that i have to use "volatile" variables in my loop, otherwise they are lost. But using volatile variables slowdowns my loop.
the_drug
@Oli: It should. I'll edit now — wasn't really paying attention last night ;)
You
A: 

If you don't want to call a time getting function each time through the loop and are on a system that has alarm (POSIXes like Unix, Linux, BSD...) you can do:

static volatile int timeout = 0;

void handle_alrm(int sig) {
     timeout = 1;
}

int main(void) {
    signal(SIGALRM, handle_alrm);
    ...
    timeout = 0;
    alarm(5);
    while (!timeout) {
       do_work();
    }
    alarm(0); // If the signal didn't fire yet we can turn it off now.
    ...

Signals can have other side effects (like kicking you out of system calls). You should look into these before relying on them.

nategoose
Does timeout actually need to be volatile? And if so, should it just be a `sig_atomic_t`? I ask because every time I do anything with signals, I always have to look it all up over again...
Steve Jessop
In this context I would use both; I can make an argument that either/both of them are unnecessary, but they won't do any harm and they *might* save your ass.
Zack
@Steve: I was going to make it `sig_atomic_t` but I thought "that might not be available on Windows" and then forgot to go back and change it when I realized that `alarm` might not be available there either.
nategoose
@Steve: As far as making it volatile, I think it does need to be this way, but even if it is not if you restrict your access to it to just the types in my example it should not cause any inefficiency or extra instructions in the program.
nategoose
@Zack: If either getting the new time or using alarms are implemented correctly the other should not be necessary, but it could save you in the case that you did timing math wrong. It may also be the case that SIGALRM isn't available (either in use somewhere else in the program or just not on the target platform).
nategoose
`volatile` here is not about whether or not alarms are implemented correctly, but about whether, in its absence, a sufficiently aggressive compiler might deduce that `handle_alrm` is never called from inside the loop, therefore `timeout` never becomes 1, therefore the loop never terminates. By me this is a pretty stretched but not totally implausible hypothetical. The case for `sig_atomic_t` is about obsolete memory busses that don't have the full complement of {8,16,32,64}-bit atomic write operations. Odds are that even on such a machine, `int` writes *are* atomic, but it's not guaranteed.
Zack
@Zack: The statement that starts with `volatile` in your comment - yes. I do disagree that a compiler optimizing out rereading and comparing the variable in the loop is stretched. Compilers are generally ignorant of signals and interrupts (even when they have extensions to support them). As far as using `sig_atomic_t` I would not refer to such buses as obsolete or new architectures with this behavior won't be in our future. Both larger and smaller types being used for this can be problematic.
nategoose