LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   confused of using usleep & sleep (https://www.linuxquestions.org/questions/programming-9/confused-of-using-usleep-and-sleep-736835/)

ag2uki 06-30-2009 10:18 PM

confused of using usleep & sleep
 
Dear all member,

I'm trying to create new C program in linux which uses usleep function. The simplified code looks like below.
Code:

#include <stdio.h>

int main(void)
{
  printf("Hello world before sleep.");
  usleep(2000000);
  printf("Hello world after sleep.");
}

After compiling, i tried to execute it. It should print the first sentence first, then wait for 2 seconds to print the last sentences.
But, the program do not work like what exactly i want. The program waits 2 seconds to print two sentences.

I created similar program using sleep(ms) function for windows. It successfully compiled and worked properly like it should.

Please help. I have run out of time just for this.

Thank you.
ag2uki

Uncle_Theodore 06-30-2009 11:13 PM

Try it like this
Code:

#include <stdio.h>

int main(void)
{
  printf("Hello world before sleep.\n");
  usleep(2000000);
  printf("Hello world after sleep.\n");
}

Does it work now? If not, try

Code:

#include <stdio.h>

int main(void)
{
  printf("Hello world before sleep.\n");
  fflush(stdout);
  usleep(2000000);
  printf("Hello world after sleep.\n");
}

You have to flush the output buffer. The first "Hello" is printer in the buffer, but gets pushed out of it only by the second "Hello". :)

Strictly speaking, your code should look like this:

Code:

#include <stdio.h>
#include <unistd.h>

int main(void)
{
  printf("Hello world before sleep.\n");
  usleep(2000000);
  printf("Hello world after sleep.\n");

return 0;
}


ag2uki 07-01-2009 02:18 AM

Thanks for your reply uncle theodore, it works.
So we have to flush output buffer or add new line character ("\n") at the end of the argument of printf, is not it? Humm... It's really annoying. I have not met with things like this before. If we use another programming language, we do not have to do it. For example, I wrote a similar program using Java as programming language. Then, it works properly.
Code:

public class TestSleep {
        public static void main(String[] args) throws Exception {
                System.out.print("Hello world before sleep.");
                Thread.sleep(2000);
                System.out.print("Hello world after sleep.");
        }
}

It's OK. I can accept this solution. However, I still have a question in my mind, which is "why so?"

wje_lq 07-01-2009 05:17 AM

Quote:

Originally Posted by ag2uki (Post 3592590)
So we have to flush output buffer or add new line character ("\n") at the end of the argument of printf, is not it? Humm... It's really annoying.

It's not a bug; it's a feature. It makes for more coherent output if you're generating more than one stream which goes to the screen (or to a file). To see how this might help you, run this shell script. This trivial program builds two output lines, chunk by chunk.
Code:

cat > 1.c <<EOD; gcc 1.c -o 1; ./1
#include <stdio.h>

int main(void)
{
  FILE *sneeze;

  sneeze=fopen("/dev/tty","w");

  printf("beginning of main line; ");

  fprintf(sneeze,"ahhhhhh ");

  printf("end of main line\n");

  fprintf(sneeze,"CHOOOO!\n");

  return 0;

} /* main() */
EOD

The output:
Code:

beginning of main line; end of main line
ahhhhhh CHOOOO!

If you don't want this behavior, you have four ways around it. The first way is to use \n, as you already know. This code:
Code:

cat > 2.c <<EOD; gcc 2.c -o 2; ./2
#include <stdio.h>

int main(void)
{
  FILE *sneeze;

  sneeze=fopen("/dev/tty","w");

  printf("beginning of main line; \n");

  fprintf(sneeze,"ahhhhhh \n");

  printf("end of main line\n");

  fprintf(sneeze,"CHOOOO!\n");

  return 0;

} /* main() */
EOD

produces this output:
Code:

beginning of main line;
ahhhhhh
end of main line
CHOOOO!

The second way is to use fflush() after all output that you want to see right away. This shell script:
Code:

cat > 3.c <<EOD; gcc 3.c -o 3; ./3
#include <stdio.h>

int main(void)
{
  FILE *sneeze;

  sneeze=fopen("/dev/tty","w");

  printf("beginning of main line; ");
  fflush(stdout);

  fprintf(sneeze,"ahhhhhh ");
  fflush(sneeze);

  printf("end of main line\n");
  fflush(sneeze);  /* not necessary, because of the \n */

  fprintf(sneeze,"CHOOOO!\n");
  fflush(sneeze);  /* not necessary, because of the \n */

  return 0;

} /* main() */
EOD

produces this output:
Code:

beginning of main line; ahhhhhh end of main line
CHOOOO!

The third way, if you have only one output stream where you want automatic flushing and it's going to the screen, is to use standard error. Notice that in the following example, the sneeze is separated onto two lines, but the main output is on one line. Of course, that one line comes on the same line as the first part of the sneeze, but that's because the example insists on outputting the first part of the sneeze right away.
Code:

cat > 3.c <<EOD; gcc 3.c -o 3; ./3
#include <stdio.h>

int main(void)
{
  printf("beginning of main line; ");

  fprintf(stderr,"ahhhhhh ");

  printf("end of main line\n");

  fprintf(stderr,"CHOOOO!\n");

  return 0;

} /* main() */
EOD

The output:
Code:

ahhhhhh beginning of main line; end of main line
CHOOOO!

The fourth way is to use setvbuf(). This must be done before any output to the particular stream:
Code:

cat > 5.c <<EOD; gcc 5.c -o 5; ./5
#include <stdio.h>

int main(void)
{
  FILE *sneeze;

  sneeze=fopen("/dev/tty","w");

  setvbuf(stdout,NULL,_IONBF,0);
  setvbuf(sneeze,NULL,_IONBF,0);


  printf("beginning of main line; ");

  fprintf(sneeze,"ahhhhhh ");

  printf("end of main line\n");

  fprintf(sneeze,"CHOOOO!\n");

  return 0;

} /* main() */
EOD

Note that you only have to do this once per stream, and you can leave the rest of your code alone. Here's the output:
Code:

beginning of main line; ahhhhhh end of main line
CHOOOO!

Hope this helps.

Sergei Steshenko 07-01-2009 08:36 AM

Use

Code:

fprintf(stderr, ...)
- by default stderr is autoflushed.

Uncle_Theodore 07-01-2009 09:41 AM

Quote:

Originally Posted by Sergei Steshenko (Post 3592941)
Use

Code:

fprintf(stderr, ...)
- by default stderr is autoflushed.

This is definitely not a good thing to do, though. The output will show up on the screen, of course, but pipes and redirects will not work as they're supposed to. It's not Unix way... ;)

wje_lq 07-01-2009 06:52 PM

Quote:

Originally Posted by Sergei Steshenko (Post 3592941)
Use

Code:

fprintf(stderr, ...)
- by default stderr is autoflushed.

Yes, that was the third of my four ways. I guess the penalty of having an answer that's too thorough is that it's not guaranteed that everyone will fight their way through the whole answer. :)
Quote:

Originally Posted by Uncle_Theodore (Post 3593029)
The output will show up on the screen, of course, but pipes and redirects will not work as they're supposed to.

Pipes won't, but redirects can:
Code:

prog1 2> redirected_stderr.txt
prog1  > redirected_stdout.txt 2> redirected_stderr.txt
prog1 2> redirected_stderr.txt | prog2


Uncle_Theodore 07-01-2009 07:15 PM

No, that's not what I meant. If you know that your program prints to stderr when it's not supposed to, because standard output should be printed to stdout, where it's expected, then, of course, you can redirect or do the usual stuff with piping, etc. But if someone is using your program and does NOT know that, s/he is in for a lot of trouble.

Things should be done in standard way. That's why we have standards... :)

Wim Sturkenboom 07-02-2009 01:35 AM

Quote:

Originally Posted by ag2uki (Post 3592590)
It's OK. I can accept this solution. However, I still have a question in my mind, which is "why so?"

I suppose that that depends on the implementation of the functions in the different languages. printf writes to a buffer; system.out.print does not seem to do that.

Buffered output allows the system to wait till it has some time before it's written. So it can spend time on things that are more important at that moment.

Sergei Steshenko 07-02-2009 02:01 AM

Quote:

Originally Posted by Uncle_Theodore (Post 3593029)
This is definitely not a good thing to do, though. The output will show up on the screen, of course, but pipes and redirects will not work as they're supposed to. It's not Unix way... ;)

It depends.

If the author needs a diagnostic message that helps him/her to debug the program it is the UNIX way.

For example, in Perl I print all my diagnostic messages through 'warn' which outputs to STDERR.

My favorite example is

Code:

cat f1.txt f2.txt f3.txt

where, say, f2.txt doesn't exist. The error message (diagnostics) goes to stderr, normal output - to stdout


All times are GMT -5. The time now is 05:58 AM.