Revert "Revert "Make stdout/stderr async""

This reverts commit r42909

TBR=ricow@google.com
BUG=

Review URL: https://codereview.chromium.org//850333002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42910 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
sgjesse@google.com
2015-01-15 14:33:35 +00:00
parent bc1be9c45f
commit c831cdf97f
19 changed files with 192 additions and 197 deletions
@@ -36,7 +36,7 @@ class StdioAnalysisServer {
Future serveStdio() {
ByteStreamServerChannel serverChannel = new ByteStreamServerChannel(
stdin,
stdout.nonBlocking,
stdout,
socketServer.instrumentationService);
socketServer.createAnalysisServer(serverChannel);
return serverChannel.closed;
+1 -1
View File
@@ -90,7 +90,7 @@ namespace bin {
V(Stdin_SetEchoMode, 1) \
V(Stdin_GetLineMode, 0) \
V(Stdin_SetLineMode, 1) \
V(Stdout_GetTerminalSize, 1) \
V(Stdout_GetTerminalSize, 0) \
V(StringToSystemEncoding, 1) \
V(SystemEncodingToString, 1)
+1 -6
View File
@@ -45,13 +45,8 @@ void FUNCTION_NAME(Stdin_SetLineMode)(Dart_NativeArguments args) {
void FUNCTION_NAME(Stdout_GetTerminalSize)(Dart_NativeArguments args) {
intptr_t fd = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 0));
if (fd != 1 && fd != 2) {
Dart_PropagateError(Dart_NewApiError("Terminal fd must be 1 or 2"));
}
int size[2];
if (Stdout::GetTerminalSize(fd, size)) {
if (Stdout::GetTerminalSize(size)) {
Dart_Handle list = Dart_NewList(2);
Dart_ListSetAt(list, 0, Dart_NewInteger(size[0]));
Dart_ListSetAt(list, 1, Dart_NewInteger(size[1]));
+2 -1
View File
@@ -32,7 +32,7 @@ class Stdin {
class Stdout {
public:
static bool GetTerminalSize(intptr_t fd, int size[2]);
static bool GetTerminalSize(int size[2]);
private:
DISALLOW_ALLOCATION();
@@ -43,3 +43,4 @@ class Stdout {
} // namespace dart
#endif // BIN_STDIO_H_
+3 -2
View File
@@ -65,9 +65,9 @@ void Stdin::SetLineMode(bool enabled) {
}
bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
bool Stdout::GetTerminalSize(int size[2]) {
struct winsize w;
if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w)) == 0 &&
if (NO_RETRY_EXPECTED(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)) == 0 &&
(w.ws_col != 0 || w.ws_row != 0)) {
size[0] = w.ws_col;
size[1] = w.ws_row;
@@ -80,3 +80,4 @@ bool Stdout::GetTerminalSize(intptr_t fd, int size[2]) {
} // namespace dart
#endif // defined(TARGET_OS_LINUX)
+2 -2
View File
@@ -65,9 +65,9 @@ void Stdin::SetLineMode(bool enabled) {
}
bool Stdout::GetTerminalSize(int fd, int size[2]) {
bool Stdout::GetTerminalSize(int size[2]) {
struct winsize w;
if (NO_RETRY_EXPECTED(ioctl(fd, TIOCGWINSZ, &w) == 0) &&
if (NO_RETRY_EXPECTED(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) &&
(w.ws_col != 0 || w.ws_row != 0)) {
size[0] = w.ws_col;
size[1] = w.ws_row;
+15 -8
View File
@@ -17,13 +17,20 @@ patch class _StdIOUtils {
}
static _getStdioOutputStream(int fd) {
wrap(sink) {
if (fd == 1) {
return new Stdout._(sink);
} else {
return new _StdSink(sink);
}
}
assert(fd == 1 || fd == 2);
switch (_getStdioHandleType(fd)) {
case _STDIO_HANDLE_TYPE_TERMINAL:
case _STDIO_HANDLE_TYPE_PIPE:
case _STDIO_HANDLE_TYPE_SOCKET:
case _STDIO_HANDLE_TYPE_FILE:
return new Stdout._(new IOSink(new _StdConsumer(fd)), fd);
return wrap(new IOSink(new _FileStreamConsumer.fromStdio(fd)));
default:
throw new FileSystemException("Unsupported stdin type");
}
@@ -56,27 +63,27 @@ patch class Stdin {
}
patch class Stdout {
/* patch */ bool _hasTerminal(int fd) {
/* patch */ bool get hasTerminal {
try {
_terminalSize(fd);
_terminalSize;
return true;
} catch (_) {
return false;
}
}
/* patch */ int _terminalColumns(int fd) => _terminalSize(fd)[0];
/* patch */ int _terminalLines(int fd) => _terminalSize(fd)[1];
/* patch */ int get terminalColumns => _terminalSize[0];
/* patch */ int get terminalLines => _terminalSize[1];
static List _terminalSize(int fd) {
var size = _getTerminalSize(fd);
static List get _terminalSize {
var size = _getTerminalSize();
if (size is! List) {
throw new StdoutException("Could not get terminal size", size);
}
return size;
}
static _getTerminalSize(int fd) native "Stdout_GetTerminalSize";
static _getTerminalSize() native "Stdout_GetTerminalSize";
}
+2 -7
View File
@@ -65,13 +65,8 @@ void Stdin::SetLineMode(bool enabled) {
}
bool Stdout::GetTerminalSize(int fd, int size[2]) {
HANDLE h;
if (fd == 1) {
h = GetStdHandle(STD_OUTPUT_HANDLE);
} else {
h = GetStdHandle(STD_ERROR_HANDLE);
}
bool Stdout::GetTerminalSize(int size[2]) {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO info;
if (!GetConsoleScreenBufferInfo(h, &info)) return false;
size[0] = info.srWindow.Right - info.srWindow.Left + 1;
@@ -495,15 +495,15 @@ class Stdin {
@patch
class Stdout {
@patch
bool _hasTerminal(int fd) {
bool get hasTerminal {
throw new UnsupportedError("Stdout.hasTerminal");
}
@patch
int _terminalColumns(int fd) {
int get terminalColumns {
throw new UnsupportedError("Stdout.terminalColumns");
}
@patch
int _terminalLines(int fd) {
int get terminalLines {
throw new UnsupportedError("Stdout.terminalLines");
}
}
+97
View File
@@ -0,0 +1,97 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart.io;
Console _console;
Console get console {
if (_console == null) {
_console = new Console._();
}
return _console;
}
/**
* [Console] provides synchronous write access to stdout and stderr.
*
* The direct access to stdout and stderr through [stdout] and [stderr]
* provides non-blocking async operations.
*/
class Console {
final ConsoleSink _stdout;
final ConsoleSink _stderr;
Console._()
: _stdout = new ConsoleSink._(1),
_stderr = new ConsoleSink._(2);
/**
* Write to stdout.
*/
ConsoleSink get log => _stdout;
/**
* Write to stderr.
*/
ConsoleSink get error => _stderr;
}
/**
* Sink class used for console writing.
*
* This class has a call method so you can call it directly. Calling
* it directly is the same as calling its `writeln` method.
*/
class ConsoleSink implements Sink<List<int>>, StringSink {
IOSink _sink;
ConsoleSink._(int fd) {
_sink = new IOSink(new _ConsoleConsumer(fd));
}
void call([Object message = ""]) => _sink.writeln(message);
void add(List<int> data) => _sink.add(data);
void close() {}
void write(Object obj) => _sink.write(obj);
void writeAll(Iterable objects, [String separator=""]) =>
_sink.writeAll(objects, separator);
void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
void writeln([Object obj=""]) => _sink.writeln(obj);
}
class _ConsoleConsumer implements StreamConsumer<List<int>> {
final _file;
_ConsoleConsumer(int fd) : _file = _File._openStdioSync(fd);
Future addStream(Stream<List<int>> stream) {
var completer = new Completer();
var sub;
sub = stream.listen(
(data) {
try {
_file.writeFromSync(data);
} catch (e, s) {
sub.cancel();
completer.completeError(e, s);
}
},
onError: completer.completeError,
onDone: completer.complete,
cancelOnError: true);
return completer.future;
}
Future close() {
_file.closeSync();
return new Future.value();
}
}
+1
View File
@@ -212,6 +212,7 @@ import 'dart:typed_data';
part 'bytes_builder.dart';
part 'common.dart';
part 'console.dart';
part 'crypto.dart';
part 'data_transformer.dart';
part 'directory.dart';
+1
View File
@@ -6,6 +6,7 @@
'sources': [
'bytes_builder.dart',
'common.dart',
'console.dart',
'crypto.dart',
'data_transformer.dart',
'directory.dart',
+8 -62
View File
@@ -149,29 +149,17 @@ class Stdin extends _StdStream implements Stream<List<int>> {
/**
* [Stdout] represents the [IOSink] for either `stdout` or `stderr`.
* [Stdout] exposes methods to query the terminal for properties.
*
* It provides a *blocking* `IOSink`, so using this to write will block until
* the output is written.
*
* In some situations this blocking behavior is undesirable as it does not
* provide the same non-blocking behavior as dart:io in general exposes.
* Use the property [nonBlocking] to get an `IOSink` which has the non-blocking
* behavior.
*
* This class can also be used to check whether `stdout` or `stderr` is
* connected to a terminal and query some terminal properties.
* Use [hasTerminal] to test if there is a terminal associated to stdout.
*/
class Stdout extends _StdSink implements IOSink {
final int _fd;
IOSink _nonBlocking;
Stdout._(IOSink sink, this._fd) : super(sink);
Stdout._(IOSink sink) : super(sink);
/**
* Returns true if there is a terminal attached to stdout.
*/
bool get hasTerminal => _hasTerminal(_fd);
external bool get hasTerminal;
/**
* Get the number of columns of the terminal.
@@ -179,7 +167,7 @@ class Stdout extends _StdSink implements IOSink {
* If no terminal is attached to stdout, a [StdoutException] is thrown. See
* [hasTerminal] for more info.
*/
int get terminalColumns => _terminalColumns(_fd);
external int get terminalColumns;
/**
* Get the number of lines of the terminal.
@@ -187,21 +175,7 @@ class Stdout extends _StdSink implements IOSink {
* If no terminal is attached to stdout, a [StdoutException] is thrown. See
* [hasTerminal] for more info.
*/
int get terminalLines => _terminalLines(_fd);
external bool _hasTerminal(int fd);
external int _terminalColumns(int fd);
external int _terminalLines(int fd);
/**
* Get a non-blocking `IOSink`.
*/
IOSink get nonBlocking {
if (_nonBlocking == null) {
_nonBlocking = new IOSink(new _FileStreamConsumer.fromStdio(_fd));
}
return _nonBlocking;
}
external int get terminalLines;
}
@@ -216,34 +190,6 @@ class StdoutException implements IOException {
}
}
class _StdConsumer implements StreamConsumer<List<int>> {
final _file;
_StdConsumer(int fd) : _file = _File._openStdioSync(fd);
Future addStream(Stream<List<int>> stream) {
var completer = new Completer();
var sub;
sub = stream.listen(
(data) {
try {
_file.writeFromSync(data);
} catch (e, s) {
sub.cancel();
completer.completeError(e, s);
}
},
onError: completer.completeError,
onDone: completer.complete,
cancelOnError: true);
return completer.future;
}
Future close() {
_file.closeSync();
return new Future.value();
}
}
class _StdSink implements IOSink {
final IOSink _sink;
@@ -281,7 +227,7 @@ class StdioType {
Stdin _stdin;
Stdout _stdout;
Stdout _stderr;
IOSink _stderr;
/// The standard input stream of data read by this program.
@@ -303,7 +249,7 @@ Stdout get stdout {
/// The standard output stream of errors written by this program.
Stdout get stderr {
IOSink get stderr {
if (_stderr == null) {
_stderr = _StdIOUtils._getStdioOutputStream(2);
}
+31
View File
@@ -0,0 +1,31 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:io";
class Message {
final message;
Message(this.message);
toString() => message;
}
void test(ConsoleSink sink) {
sink.add([65, 66, 67]);
sink.write('DEF');
sink.writeAll(['GH', 'I']);
sink.writeCharCode(74);
sink.writeln('KLM');
}
void main(List<String> arguments) {
console.log('stdout');
console.error('stderr');
console.log();
console.error();
console.log(new Message('tuodts'));
console.error(new Message('rredts'));
test(console.log);
test(console.error);
exit(1);
}
@@ -1,4 +1,4 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@@ -8,8 +8,7 @@ import "dart:io";
import "package:expect/expect.dart";
void main() {
var script =
Platform.script.resolve("stdio_nonblocking_script.dart").toFilePath();
var script = Platform.script.resolve("console_script.dart").toFilePath();
Process.run(Platform.executable,
['--checked', script],
stdoutEncoding: ASCII,
@@ -1,34 +0,0 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:async";
import "dart:io";
class Message {
final message;
Message(this.message);
toString() => message;
}
void test(IOSink sink) {
sink.add([65, 66, 67]);
sink.write('DEF');
sink.writeAll(['GH', 'I']);
sink.writeCharCode(74);
sink.writeln('KLM');
}
void main(List<String> arguments) {
stdout.nonBlocking.writeln('stdout');
stderr.nonBlocking.writeln('stderr');
stdout.nonBlocking.writeln();
stderr.nonBlocking.writeln();
stdout.nonBlocking.writeln(new Message('tuodts'));
stderr.nonBlocking.writeln(new Message('rredts'));
test(stdout.nonBlocking);
test(stderr.nonBlocking);
Future.wait([stdout.nonBlocking.close(),
stderr.nonBlocking.close()])
.then((_) => exit(1));
}
@@ -1,44 +0,0 @@
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
import "dart:async";
import "dart:convert";
import "dart:io";
callIOSink(IOSink sink) {
// Call all methods on IOSink.
sink.encoding = ASCII;
Expect.equals(ASCII, sink.encoding);
sink.write("Hello\n");
sink.writeln("Hello");
sink.writeAll(["H", "e", "l", "lo\n"]);
sink.writeCharCode(72);
sink.add([101, 108, 108, 111, 10]);
var controller = new StreamController(sync: true);
var future = sink.addStream(controller.stream);
controller.add([72, 101, 108]);
controller.add([108, 111, 10]);
controller.close();
future.then((_) {
controller = new StreamController(sync: true);
controller.stream.pipe(sink);
controller.add([72, 101, 108]);
controller.add([108, 111, 10]);
controller.close();
});
}
main() {
callIOSink(stdout.nonBlocking);
stdout.nonBlocking.done.then((_) {
callIOSink(stderr.nonBlocking);
stderr.nonBlocking.done.then((_) {
stdout.close();
stderr.close();
});
});
}
@@ -1,23 +0,0 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:io";
import "package:expect/expect.dart";
void testTerminalSize(std) {
if (std.hasTerminal) {
Expect.notEquals(0, std.terminalColumns);
Expect.notEquals(0, std.terminalLines);
} else {
Expect.throws(() => std.terminalColumns, (e) => e is StdoutException);
Expect.throws(() => std.terminalLines, (e) => e is StdoutException);
}
}
void main() {
testTerminalSize(stdout);
testTerminalSize(stderr);
}
+22
View File
@@ -0,0 +1,22 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "dart:io";
import "package:expect/expect.dart";
void testTerminalSize() {
if (stdout.hasTerminal) {
Expect.notEquals(0, stdout.terminalColumns);
Expect.notEquals(0, stdout.terminalLines);
} else {
Expect.throws(() => stdout.terminalColumns, (e) => e is StdoutException);
Expect.throws(() => stdout.terminalLines, (e) => e is StdoutException);
}
}
void main() {
testTerminalSize();
}