Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to define a loop to be run for some seconds/minutes long

My purpose is to execute a while loop for a defined time (e.g. 90 seconds for this example). It does not have to be exactly 90 s, but 1-2 second inaccuracy is acceptable. I trued to use clock()` function for this purpose:

int main(void){
      clock_t start, end;
      volatile double elapsed;
      start = clock();
      int terminate = 1;
      while(terminate)
      {
              end = clock();
              elapsed = ((double) (end-start)) / (double) CLOCKS_PER_SEC *1000;
              printf("elapsed time:%f\n",elapsed);
              if(elapsed >= 90.0)
                        terminate = 0;
               usleep(50000);
       }
      printf("done..\n");
    return 0;
}

when I run it on my laptop (x86, 3.13 kernel, gcc 4.8.2), my stopwatch measures 72 seconds for it to be completed. (1000 was necessary to have the elapsed in seconds accuracy on my laptop)

When I run it on an ARM device (armv5tejl, 3.12 kernel, gcc 4.6.3) it takes 58 seconds to complete the code. (I needed to used 100 on elapsed on the armv5).

I run the code on a room temperature, so the clock should be stable. I know that kernel sleeps the threads and has inaccuracy with time to wake them up, etc. Therefore, as I said previously I don't expect to get a perfect timing, but it should have some accuracy.

I had tried to use only usleep (even nanosleep) but the resolution was not good as well. At the end I come up with the the bottom code that fetches the system time (hour, minute, second) then calculate the elapsed time. And it works with a good accuracy.

I wonder if there is another solution that would be less costly to use?

typedef struct{
    int hour;
    int minute;
    int second;
} timeInfo;

timeInfo getTimeInfo(void){
    timeInfo value2return;
    time_t rawtime;
    struct tm * timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    value2return.hour = timeinfo->tm_hour;
    value2return.minute = timeinfo->tm_min;
    value2return.second = timeinfo->tm_sec;
    return value2return;
}

int checkElapsedTime(const timeInfo *Start, const timeInfo *Stop, const int Reference){
    if(Stop->hour < Start->hour){
        printf("1:%d\n", (Stop->hour +24) *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second));
         if( ( (Stop->hour +24) *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second)) >= Reference )
            return 0; //while(0): terminate the loop
         else
             return 1; //while(1)
    }else{
        printf("2:%d\n",Stop->hour *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second));
        if( (Stop->hour *3600 + Stop->minute *60 + Stop->second - (Start->hour *3600 +Start->minute * 60 + Start->second)) >= Reference )
            return 0;
        else
            return 1;
    }
}

int main(void){

    timeInfo stop, start = getTimeInfo();
    int terminate = 1;
    while(terminate)
    {
        stop = getTimeInfo();
        terminate = checkElapsedTime(&start, &stop, 90);
        usleep(5000); //to decrease the CPU load
    }

    printf("terminated\n");

    return 0;
}

Lastly, I need to run it inside a pthread.

like image 776
Angs Avatar asked Aug 24 '14 20:08

Angs


People also ask

How do you make a program run for a certain time in python?

How do I run a specific time function in Python? Timer() to schedule function calls. However, if you want a particular function to wait for a specific time in Python, we can use the threading. Timer() method from the threading module.

Do while loops only run once?

There are two variations of the while loop – while and do-While. The difference between the two is that do-while runs at least once. A while loop might not even execute once if the condition is not met. However, do-while will run once, then check the condition for subsequent loops.


2 Answers

  1. Use time() vs. clock(). Coding goal is to determine wall time elapsed and not processor time used.

    Current code calculated the process time elapsed * 1000 and compared that to 90 seconds.

    clock(), which @uesp implied, returns "The clock function determines the processor time used." C11dr §7.27.2.1 2.

    time() which returns "The time function determines the current calendar time" §7.27.2.4 2

    difftime() does a nice job of finding the difference between 2 time_t (in whatever units/type they are) and returning the difference in seconds.

    int main(void) {
       time_t start, end;
       double elapsed;  // seconds
       start = time(NULL);
       int terminate = 1;
       while (terminate) {
         end = time(NULL);
         elapsed = difftime(end, start);
         if (elapsed >= 90.0 /* seconds */)
           terminate = 0;
         else  // No need to sleep when 90.0 seconds elapsed.
           usleep(50000);
       }
       printf("done..\n");
       return 0;
     }
    
  2. Minor: Note: when using clock(), no need for * 1000. On a windows based machine running gcc, for me, clock() also returned the calling process CPU time.

    elapsed = ((double) (end-start)) / (double) CLOCKS_PER_SEC *1000;
    elapsed = ((double) (end-start)) / CLOCKS_PER_SEC;
    
  3. Minor: No need for volatile. elapsed is only changing due to this code.

    // volatile double elapsed;
    double elapsed;
    
like image 151
chux - Reinstate Monica Avatar answered Nov 04 '22 13:11

chux - Reinstate Monica


The reason your first version doesn't seem to work is that on Linux clock() measures the used CPU time and not the real time (see here). Since you are sleeping the process then the real and CPU times don't match up. The solution is to check the real clock time as in your second example.

Note that on Windows clock() does give you the real clock time (see here).

like image 45
uesp Avatar answered Nov 04 '22 12:11

uesp