Don't automatically flush on every System.write().

It's handy because it ensures writes are flushed to the terminal before
any calls to read from stdin, but it's also gratuitously slow.

Instead, added a Stdout class with an explicit flush() method that can
be called by the user.

Fix #445.
This commit is contained in:
Bob Nystrom
2017-10-09 07:16:05 -07:00
parent c4b0f83cb3
commit 2021e086bf
9 changed files with 41 additions and 2 deletions
+1
View File
@@ -6,3 +6,4 @@ Provides access to operating system streams and the file system.
* [File](file.html) * [File](file.html)
* [Stat](stat.html) * [Stat](stat.html)
* [Stdin](stdin.html) * [Stdin](stdin.html)
* [Stdout](stdout.html)
+8
View File
@@ -29,9 +29,17 @@ been received.
Returns the byte value as a number or `null` if stdin is closed. Returns the byte value as a number or `null` if stdin is closed.
Note that output is not automatically flushed when calling this. If you want to
display a prompt before reading input, you'll want to call `Stdout.flush()`
after printing the prompt.
### **readLine**() ### **readLine**()
Reads one line of input from stdin. Blocks the current fiber until a full line Reads one line of input from stdin. Blocks the current fiber until a full line
of input has been received. of input has been received.
Returns the string of input or `null` if stdin is closed. Returns the string of input or `null` if stdin is closed.
Note that output is not automatically flushed when calling this. If you want to
display a prompt before reading input, you'll want to call `Stdout.flush()`
after printing the prompt.
+11
View File
@@ -0,0 +1,11 @@
^title Stdout Class
The standard output stream.
## Static Methods
### **flush()**
Flushes all buffered data to the stream. Ensures any data written to stdout
that is in the buffer gets written to the file or terminal that stdout is
connected to.
+2
View File
@@ -32,6 +32,7 @@
<li><a href="file-flags.html">FileFlags</a></li> <li><a href="file-flags.html">FileFlags</a></li>
<li><a href="stat.html">Stat</a></li> <li><a href="stat.html">Stat</a></li>
<li><a href="stdin.html">Stdin</a></li> <li><a href="stdin.html">Stdin</a></li>
<li><a href="stdout.html">Stdout</a></li>
</ul> </ul>
</section> </section>
</nav> </nav>
@@ -56,6 +57,7 @@
<ul> <ul>
<li><a href="stat.html">Stat</a></li> <li><a href="stat.html">Stat</a></li>
<li><a href="stdin.html">Stdin</a></li> <li><a href="stdin.html">Stdin</a></li>
<li><a href="stdout.html">Stdout</a></li>
</ul> </ul>
</td> </td>
</tr> </tr>
+5 -1
View File
@@ -43,6 +43,7 @@ extern void stdinIsRawSet(WrenVM* vm);
extern void stdinIsTerminal(WrenVM* vm); extern void stdinIsTerminal(WrenVM* vm);
extern void stdinReadStart(WrenVM* vm); extern void stdinReadStart(WrenVM* vm);
extern void stdinReadStop(WrenVM* vm); extern void stdinReadStop(WrenVM* vm);
extern void stdoutFlush(WrenVM* vm);
extern void schedulerCaptureMethods(WrenVM* vm); extern void schedulerCaptureMethods(WrenVM* vm);
extern void timerStartTimer(WrenVM* vm); extern void timerStartTimer(WrenVM* vm);
@@ -61,7 +62,7 @@ extern void timerStartTimer(WrenVM* vm);
// If you add a new class to the largest module below, make sure to bump this. // If you add a new class to the largest module below, make sure to bump this.
// Note that it also includes an extra slot for the sentinel value indicating // Note that it also includes an extra slot for the sentinel value indicating
// the end of the list. // the end of the list.
#define MAX_CLASSES_PER_MODULE 5 #define MAX_CLASSES_PER_MODULE 6
// Describes one foreign method in a class. // Describes one foreign method in a class.
typedef struct typedef struct
@@ -153,6 +154,9 @@ static ModuleRegistry modules[] =
STATIC_METHOD("readStart_()", stdinReadStart) STATIC_METHOD("readStart_()", stdinReadStart)
STATIC_METHOD("readStop_()", stdinReadStop) STATIC_METHOD("readStop_()", stdinReadStop)
END_CLASS END_CLASS
CLASS(Stdout)
STATIC_METHOD("flush()", stdoutFlush)
END_CLASS
END_MODULE END_MODULE
MODULE(os) MODULE(os)
CLASS(Platform) CLASS(Platform)
-1
View File
@@ -151,7 +151,6 @@ static WrenForeignClassMethods bindForeignClass(
static void write(WrenVM* vm, const char* text) static void write(WrenVM* vm, const char* text)
{ {
printf("%s", text); printf("%s", text);
fflush(stdout);
} }
static void reportError(WrenVM* vm, WrenErrorType type, static void reportError(WrenVM* vm, WrenErrorType type,
+6
View File
@@ -545,6 +545,12 @@ void stdinIsTerminal(WrenVM* vm)
wrenSetSlotBool(vm, 0, uv_guess_handle(stdinDescriptor) == UV_TTY); wrenSetSlotBool(vm, 0, uv_guess_handle(stdinDescriptor) == UV_TTY);
} }
void stdoutFlush(WrenVM* vm)
{
fflush(stdout);
wrenSetSlotNull(vm, 0);
}
static void allocCallback(uv_handle_t* handle, size_t suggestedSize, static void allocCallback(uv_handle_t* handle, size_t suggestedSize,
uv_buf_t* buf) uv_buf_t* buf)
{ {
+4
View File
@@ -297,3 +297,7 @@ class Stdin {
foreign static readStart_() foreign static readStart_()
foreign static readStop_() foreign static readStop_()
} }
class Stdout {
foreign static flush()
}
+4
View File
@@ -298,4 +298,8 @@ static const char* ioModuleSource =
"\n" "\n"
" foreign static readStart_()\n" " foreign static readStart_()\n"
" foreign static readStop_()\n" " foreign static readStop_()\n"
"}\n"
"\n"
"class Stdout {\n"
" foreign static flush()\n"
"}\n"; "}\n";