| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 part of dart.isolate; | |
| 6 | |
| 7 /** | |
| 8 * The initial IsolateStream available by default for this isolate. | |
| 9 * | |
| 10 * This IsolateStream is created automatically and is commonly used | |
| 11 * to establish the first communication between isolates. | |
| 12 * (See [streamSpawnFunction].) | |
| 13 */ | |
| 14 final IsolateStream stream = new IsolateStream._fromOriginalReceivePort(port); | |
| 15 | |
| 16 /** | |
| 17 * The creator of the [IsolateStream] and [IsolateSink] | |
| 18 * that allow an isolate to exchange messages with other isolates. | |
| 19 * | |
| 20 * Any message that is written into the [sink] (independent of the isolate) is | |
| 21 * sent to the [stream] where its subscribers can react to the messages. | |
| 22 */ | |
| 23 class MessageBox { | |
| 24 final IsolateStream stream; | |
| 25 final IsolateSink sink; | |
| 26 | |
| 27 external MessageBox.oneShot(); | |
| 28 external MessageBox(); | |
| 29 } | |
| 30 | |
| 31 external bool _isCloseToken(var object); | |
| 32 | |
| 33 /** | |
| 34 * Together with [IsolateSink], the only means of | |
| 35 * communication between isolates. | |
| 36 * | |
| 37 * Each IsolateStream has a corresponding | |
| 38 * [IsolateSink]. Any message written into that sink will be delivered to | |
| 39 * the stream and then dispatched to the stream's subscribers. | |
| 40 */ | |
| 41 class IsolateStream extends Stream<dynamic> { | |
| 42 bool _isClosed = false; | |
| 43 final ReceivePort _port; | |
| 44 StreamController _controller = new StreamController(sync: true); | |
| 45 | |
| 46 IsolateStream._fromOriginalReceivePort(this._port) { | |
| 47 _port.receive((message, replyTo) { | |
| 48 assert(replyTo == null); | |
| 49 _add(message); | |
| 50 }); | |
| 51 } | |
| 52 | |
| 53 IsolateStream._fromOriginalReceivePortOneShot(this._port) { | |
| 54 _port.receive((message, replyTo) { | |
| 55 assert(replyTo == null); | |
| 56 _add(message); | |
| 57 close(); | |
| 58 }); | |
| 59 } | |
| 60 | |
| 61 void _add(var message) { | |
| 62 if (_isCloseToken(message)) { | |
| 63 close(); | |
| 64 } else { | |
| 65 _controller.sink.add(message); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 /** | |
| 70 * Closes the stream from the receiving end. | |
| 71 * | |
| 72 * Closing an already closed port has no effect. | |
| 73 */ | |
| 74 void close() { | |
| 75 if (!_isClosed) { | |
| 76 _isClosed = true; | |
| 77 _port.close(); | |
| 78 _controller.close(); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 StreamSubscription listen(void onData(event), | |
| 83 { void onError(error), | |
| 84 void onDone(), | |
| 85 bool cancelOnError}) { | |
| 86 return _controller.stream.listen(onData, | |
| 87 onError: onError, | |
| 88 onDone: onDone, | |
| 89 cancelOnError: cancelOnError); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 /** | |
| 94 * The feed for an [IsolateStream]. | |
| 95 * | |
| 96 * Any message written to [this] is delivered | |
| 97 * to its respective [IsolateStream]. | |
| 98 * [IsolateSink]s are created by [MessageBox]es. | |
| 99 * | |
| 100 * [IsolateSink]s can be transmitted to other isolates. | |
| 101 */ | |
| 102 abstract class IsolateSink extends EventSink<dynamic> { | |
| 103 // TODO(floitsch): Actually it should be a StreamSink (being able to flow- | |
| 104 // control). | |
| 105 | |
| 106 /** | |
| 107 * Sends an asynchronous [message] to the linked [IsolateStream]; | |
| 108 * the message is copied to the receiving isolate. | |
| 109 * | |
| 110 * The content of [message] can be: primitive values (null, num, bool, double, | |
| 111 * String), instances of [IsolateSink]s, and lists and maps whose elements are | |
| 112 * any of these. List and maps are also allowed to be cyclic. | |
| 113 * | |
| 114 * In the special circumstances when two isolates share the same code and are | |
| 115 * running in the same process (e.g. isolates created via [spawnFunction]), it | |
| 116 * is also possible to send object instances (which would be copied in the | |
| 117 * process). This is currently only supported by the dartvm. For now, the | |
| 118 * dart2js compiler only supports the restricted messages described above. | |
| 119 */ | |
| 120 void add(dynamic message); | |
| 121 | |
| 122 void addError(errorEvent); | |
| 123 | |
| 124 /** Closing multiple times is allowed. */ | |
| 125 void close(); | |
| 126 | |
| 127 /** | |
| 128 * Tests whether [other] is an [IsolateSink] feeding into the same | |
| 129 * [IsolateStream] as this one. | |
| 130 */ | |
| 131 bool operator==(var other); | |
| 132 } | |
| 133 | |
| 134 | |
| 135 /** | |
| 136 * Creates and spawns an isolate that shares the same code as the current | |
| 137 * isolate, but that starts from the specified function. | |
| 138 * | |
| 139 * The [topLevelFunction] argument must be | |
| 140 * a static top-level function or a static method that takes no arguments. | |
| 141 * | |
| 142 * When any isolate starts (even the main script of the application), a default | |
| 143 * [IsolateStream] is created for it. This sink is available from the top-level | |
| 144 * getter [stream] defined in this library. | |
| 145 * | |
| 146 * [spawnFunction] returns an [IsolateSink] feeding into the child isolate's | |
| 147 * default stream. | |
| 148 * | |
| 149 * The optional [unhandledExceptionCallback] argument is invoked whenever an | |
| 150 * exception inside the isolate is unhandled. It can be seen as a big | |
| 151 * `try/catch` around everything that is executed inside the isolate. The | |
| 152 * callback should return `true` if it was able to handle the exception. | |
| 153 */ | |
| 154 external IsolateSink streamSpawnFunction( | |
| 155 void topLevelFunction(), | |
| 156 [bool unhandledExceptionCallback(IsolateUnhandledException e)]); | |
| OLD | NEW |