blob: ceb5c82f8752c324fc9e9d471711323a3950e776 [file] [log] [blame]
// 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:async';
import 'dart:io';
/// Merges all streams in [streams] into a single stream that emits all of their
/// values.
///
/// The returned stream will be closed only when every stream in [streams] is
/// closed.
Stream mergeStreams(Iterable<Stream> streams) {
var subscriptions = new Set();
var controller;
controller = new StreamController(onListen: () {
for (var stream in streams) {
var subscription;
subscription = stream.listen(controller.add,
onError: controller.addError,
onDone: () {
subscriptions.remove(subscription);
if (subscriptions.isEmpty) controller.close();
});
subscriptions.add(subscription);
}
}, onCancel: () {
for (var subscription in subscriptions) {
subscription.cancel();
}
}, onPause: () {
for (var subscription in subscriptions) {
subscription.pause();
}
}, onResume: () {
for (var subscription in subscriptions) {
subscription.resume();
}
}, sync: true);
return controller.stream;
}
/// A cache for [supportsIpV6].
bool _supportsIpV6;
/// Returns whether this computer supports binding to IPv6 addresses.
Future<bool> get supportsIpV6 {
if (_supportsIpV6 != null) return new Future.value(_supportsIpV6);
return ServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0).then((socket) {
_supportsIpV6 = true;
socket.close();
return true;
}).catchError((error) {
if (error is! SocketException) throw error;
_supportsIpV6 = false;
return false;
});
}