| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:io'; | 6 import 'dart:io'; |
| 7 | 7 |
| 8 /// Merges all streams in [streams] into a single stream that emits all of their | |
| 9 /// values. | |
| 10 /// | |
| 11 /// The returned stream will be closed only when every stream in [streams] is | |
| 12 /// closed. | |
| 13 Stream mergeStreams(Iterable<Stream> streams) { | |
| 14 var subscriptions = new Set(); | |
| 15 var controller; | |
| 16 controller = new StreamController(onListen: () { | |
| 17 for (var stream in streams) { | |
| 18 var subscription; | |
| 19 subscription = stream.listen(controller.add, | |
| 20 onError: controller.addError, | |
| 21 onDone: () { | |
| 22 subscriptions.remove(subscription); | |
| 23 if (subscriptions.isEmpty) controller.close(); | |
| 24 }); | |
| 25 subscriptions.add(subscription); | |
| 26 } | |
| 27 }, onCancel: () { | |
| 28 for (var subscription in subscriptions) { | |
| 29 subscription.cancel(); | |
| 30 } | |
| 31 }, onPause: () { | |
| 32 for (var subscription in subscriptions) { | |
| 33 subscription.pause(); | |
| 34 } | |
| 35 }, onResume: () { | |
| 36 for (var subscription in subscriptions) { | |
| 37 subscription.resume(); | |
| 38 } | |
| 39 }, sync: true); | |
| 40 | |
| 41 return controller.stream; | |
| 42 } | |
| 43 | |
| 44 /// A cache for [supportsIpV6]. | 8 /// A cache for [supportsIpV6]. |
| 45 bool _supportsIpV6; | 9 bool _supportsIpV6; |
| 46 | 10 |
| 47 /// Returns whether this computer supports binding to IPv6 addresses. | 11 /// Returns whether this computer supports binding to IPv6 addresses. |
| 48 Future<bool> get supportsIpV6 { | 12 Future<bool> get supportsIpV6 async { |
| 49 if (_supportsIpV6 != null) return new Future.value(_supportsIpV6); | 13 if (_supportsIpV6 != null) return _supportsIpV6; |
| 50 | 14 |
| 51 return ServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0).then((socket) { | 15 try { |
| 16 var socket = await ServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0); |
| 52 _supportsIpV6 = true; | 17 _supportsIpV6 = true; |
| 53 socket.close(); | 18 socket.close(); |
| 54 return true; | 19 return true; |
| 55 }).catchError((error) { | 20 } on SocketException catch (_) { |
| 56 if (error is! SocketException) throw error; | |
| 57 _supportsIpV6 = false; | 21 _supportsIpV6 = false; |
| 58 return false; | 22 return false; |
| 59 }); | 23 } |
| 60 } | 24 } |
| OLD | NEW |