www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Control flushing to stdout... core.osthread.Thread + arsd.terminal

reply aberba <karabutaworld gmail.com> writes:
I have this code which take two inputs. I expect "Wait, signing 
you in ..." to be written to stdout before Thread.sleep() kicks 
in but it somehow doesn't follow that sequence. I believe its a 
normal stdout behaviour since its buffered.

How can I make Thread.sleep() only run AFTER "Wait, signing you 
in ..." is written (force flushed) to stdout?

import core.thread.osthread, std.datetime;
import arsd.terminal;

void main()
{
     auto terminal = Terminal(ConsoleOutputType.linear);
     terminal.setTitle("App");

     // this is possible too but you MUST have an indexed png 
which might be hard to make if you aren't ready for it.
     // terminal.changeWindowIcon("assets/icon.png");

     terminal.writeln("hi");

     auto got = terminal.getline("Username: ");
     auto code = terminal.getline("Password: ");

     const timeInSeconds = 5;
     terminal.writeln("Wait, signing you in ...");


     Thread.sleep(timeInSeconds.seconds);


     terminal.writeln("username is ", got);
     terminal.writeln("code is ", code);
}
Jun 05 2020
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 5 June 2020 at 11:45:31 UTC, aberba wrote:
 How can I make Thread.sleep() only run AFTER "Wait, signing you 
 in ..." is written (force flushed) to stdout?
just use explicit `terminal.flush();` any time you want the output to appear immediately. Terminal does its own aggressive buffering internally (which I kinda regret) and only flushes with 1) it is full or 2) you ask for input, unless you call that flush function.
Jun 05 2020
next sibling parent reply aberba <karabutaworld gmail.com> writes:
On Friday, 5 June 2020 at 12:28:17 UTC, Adam D. Ruppe wrote:
 On Friday, 5 June 2020 at 11:45:31 UTC, aberba wrote:
 How can I make Thread.sleep() only run AFTER "Wait, signing 
 you in ..." is written (force flushed) to stdout?
just use explicit `terminal.flush();` any time you want the output to appear immediately. Terminal does its own aggressive buffering internally (which I kinda regret) and only flushes with 1) it is full or 2) you ask for input, unless you call that flush function.
Why was the initial decision to handle buffering that way in terminal?
Jun 05 2020
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 5 June 2020 at 20:05:28 UTC, aberba wrote:
 Why was the initial decision to handle buffering that way in 
 terminal?
More buffering = more speed, it actually makes a surprisingly big difference sometimes, like you can notice the lag with your eyes alone as it prints in the more extreme cases, seeing the cursor bounce around the screen and such when doing a full screen update. So I have it internally gathering everything together into one big buffer, all your moveTo, color, and writeln calls gather it. Then the flush updates as much of the screen as possible in one go. Since it auto-flushes when you get input or when the program exits, it works pretty well a lot of the time... but when you are like "working..." then the program pauses, it doesn't help at all. If I was doing it again today, I think I'd probably make it flush a little more often automatically, at least with the linear output mode.
Jun 05 2020
prev sibling parent reply aberba <karabutaworld gmail.com> writes:
On Friday, 5 June 2020 at 12:28:17 UTC, Adam D. Ruppe wrote:
 On Friday, 5 June 2020 at 11:45:31 UTC, aberba wrote:
 How can I make Thread.sleep() only run AFTER "Wait, signing 
 you in ..." is written (force flushed) to stdout?
just use explicit `terminal.flush();` any time you want the output to appear immediately. Terminal does its own aggressive buffering internally (which I kinda regret) and only flushes with 1) it is full or 2) you ask for input, unless you call that flush function.
Ooop. Forgot to say thanks. Thanks, works as expected now. Didn't come to mind to lookup from terminal docs. Thought it was a Dlang/OS problem.
Jun 05 2020
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 5 June 2020 at 20:11:16 UTC, aberba wrote:
 Didn't come to mind to lookup from terminal docs. Thought it 
 was a Dlang/OS problem.
Yeah, the OS by itself rarely buffers output like this, but both the C library (on which std.stdio is built) and my Terminal object do (they do separately btw, which is why I suggest you avoid mixing together terminal.writeln and regular stdout.writeln, since they can intermix unpredictably as they flush at different calls). The C one tends to auto-flush on newline, unless it is piped to another program... which confuses poor users on IDEs, since from the program's perspective, the IDE console is another program! So your output can be delayed differently there vs direct to the user's screen. (My terminal.d will actually throw an exception if you try to use it in such an environment. You need to check Terminal.stdoutIsTerminal() if you want to handle that case differently. This is another decision I semi-regret and might change in the future, since a lot of things do work fine in that environment, you just can't move the cursor around in it.) Anyway the point is just that output functions often pretend to succeed while actually just buffering it internally. Unless the docs say otherwise when using one of these, there's no guarantee it will actually display until you call the library's flush function (in std.stdio btw it is `stdout.flush();`, in C it is `fflush(stdio);`) or close the file.
Jun 05 2020