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 |