4

Suppose I have C++ code such as

#include "myheaderfiles.h"
//..some stuff
//...some more stuff
int main()
{
   double milliseconds;
   int seconds;
   int minutes;
   int timelimit=2;
   ...
   ...
   //...code here that increments 
   //.....milliseconds,seconds, and minutes

   while(minutes <=timelimit)
   {
      //...do stuff
      if(milliseconds>500)
      {
         //...do stuff 
         //...every half second
      } //end if
   } //end while
}//end main

The program will run fine and does what its supposed to do but it will use up 90%+ of my cpu.

It was suggested to me to use usleep() in my while loop ever 100ms or so since I really only care about doing stuff every 500ms anyway. That way, it hog the CPU when its not needed.

So I added it to my while loop like so

   while(minutes <=timelimit)
   {
      //...do stuff
      if(milliseconds>500)
      {
         //...do stuff 
         //...every half second
      } //end if
      usleep(100000);
   } //end while

It compiles fine, but when I run it, the program will hang right at usleep and never return. I read somewhere that before calling usleep, one needs to flush all buffers, so I flushed all file streams and couts etc etc. Still no luck.

I've searched for 2 days for a solution. I've used sleep() too, with no luck.

I found a few alternatives but they seem complicated and will add a lot of code to my program that I dont really fully understand which will complicate it and make it messy, plus it might not work.

I never really put too much thought in my while() loops before because most of the programs I wrote were for microcontrollers or FPGAs which is no problem to hog the processor.

If anyone can help.... any resources, links,books? Thanks.

ChumbiChubaGo
  • 968
  • 2
  • 9
  • 15
  • 2
    Please tell me you're not using CPU clock to measure time... – Mysticial Apr 11 '14 at 23:19
  • 1
    Can you show your complete while() loop. There could be many reason for this and this is known as busy loop problem. usleep() would not cause any hang. There is something else wrong in your code. – Mantosh Kumar Apr 11 '14 at 23:20
  • I'm wondering -- is there something to do for the program or is it just idly polling somewhere? If there's something to do, getting it done faster shouldn't hurt (on *nix or windows one could turn down the prio though). If you are polling, perhaps there is an event driven solution? – Peter - Reinstate Monica Apr 11 '14 at 23:27
  • 1
    why don't you just register to have a timer wake up and call you every half second if that's what you want? this doesn't seem like the right solution to begin with. are you sure it's hanging at usleep? maybe you're not incrementing 'milliseconds' correctly. – Adam Bryant Apr 11 '14 at 23:29
  • do you use signal in your program, by any chance? –  Apr 12 '14 at 00:11
  • Mysticial, yes I am measuring time with time.h. Why? – ChumbiChubaGo Apr 14 '14 at 05:15
  • Adam Bryant. If you reread what I wrote, it works fine until I put usleep in there. I know it hangs at usleep because it executes everything up until it gets to usleep. If I remove usleep, the program runs fine, it just takes up 90% of the cpu, but it does exactly what its designed to do smoothly. I just dont want it to hog the cpu! – ChumbiChubaGo Apr 14 '14 at 05:16
  • Can anyone provide a very simple code with a main while loop that successfully uses usleep for me? I would be so grateful! – ChumbiChubaGo Apr 14 '14 at 05:21
  • Please don't tell me you have the intent of purposely slowing down the execution of your program? Have you thought about people not wanting to wait longer, or those who have slower CPUs and will require even more time? – rubenvb Apr 22 '14 at 08:39

3 Answers3

3

Your approach somewhat comes from the wrong end. A program should consume 90-100% CPU as long as it has something useful to do (and it should block otherwise, consuming zero CPU).
Sleeping in between will cause execution being longer for no good reason, and consume more energy than just doing the work as fast as possible (at 100% CPU) and then completely blocking until more work is available or until some other significant thing (e.g. half a second has passed, if that matters for you) happens.

With that in mind, structure your program in a way conceptually like:

while(blocking_call() != exit_condition)
{
    while(have_work)
        do_work();
}

Also, do not sleep during execution, but use timers (e.g. setitimer) to do something at regular intervals. Not only will this be more efficient, but also a lot more precise and reliable.

How exactly you implement this depends on how portable you want your software to be. Under Ubuntu/Linux, you can for example use APIs such as epoll_wait with eventfd rather than writing a signal handler for the timer.

Damon
  • 67,688
  • 20
  • 135
  • 185
0

This code works as expected for me (running on OSX though).

  #include <unistd.h>
  #include <iostream> 

  int main() {
    std::cout << "hello" << std::endl;

    int i = 0;
    while(i < 10) {
      ++i;
      usleep(100000);
      std::cout << "i = " << i << std::endl;                                                                                                                                        
    }
    std::cout << "bye" << std::endl;
    return 0;
  }
Buddy
  • 10,874
  • 5
  • 41
  • 58
0

There is a logical issue or maybe you're making multiple counters? Since you said you've done microcontrollers, I assume you're trying to use clock-cycles as a method of counting while calling the system timers? Also, what has me questioning is if you're recommended to use usleep(x), why are you using double for millisecond? usleep(1) is 1 microsecond == 1000 milliseconds. The sleep(x) is a counter per x second, so the system will suspend it's current task for x amount of seconds.

#include <iostream>
#include <unistd.h>

using namespace std;

#define MILLISECOND 1000
#define SECOND 1000*MILLISECOND

int main(int argc, char *argv[]){
    int time = 20;
    int sec_counter = 0;
    do{     
        cout<<sec_counter<<" second"<<endl;
        usleep(SECOND);
        sec_counter++;
    } while(sec_counter<time+1);
    return 0;
}

If you wanted to use 500ms then replace usleep(SECOND) with usleep(500*MILLISECOND). I suggest you use a debugger and step through your code to see what's happening.

Tony
  • 1
  • 1
    Just wanted to point out that 1 microsecond does not equal 1000 milliseconds, it's the other way around. You might want to revise that last part of your answer. – Nebojsa Mrmak Mar 09 '17 at 08:53