Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: sdk/lib/isolate/isolate_stream.dart

Issue 12919011: Remove streamSpawnUri and mangler. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sdk/lib/isolate/isolate_sources.gypi ('k') | sdk/lib/isolate/mangler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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 part of dart.isolate; 5 part of dart.isolate;
6 6
7 /** 7 /**
8 * The initial [IsolateStream] available by default for this isolate. This 8 * The initial [IsolateStream] available by default for this isolate. This
9 * [IsolateStream] is created automatically and it is commonly used to establish 9 * [IsolateStream] is created automatically and it is commonly used to establish
10 * the first communication between isolates (see [streamSpawnFunction] and 10 * the first communication between isolates (see [streamSpawnFunction] and
11 * [streamSpawnUri]). 11 * [streamSpawnUri]).
12 */ 12 */
13 final IsolateStream stream = new IsolateStream._fromOriginalReceivePort(port); 13 final IsolateStream stream = new IsolateStream._fromOriginalReceivePort(port);
14 14
15 /** 15 /**
16 * A [MessageBox] creates an [IsolateStream], [stream], and an [IsolateSink], 16 * A [MessageBox] creates an [IsolateStream], [stream], and an [IsolateSink],
17 * [sink]. 17 * [sink].
18 * 18 *
19 * Any message that is written into the [sink] (independent of the isolate) is 19 * Any message that is written into the [sink] (independent of the isolate) is
20 * sent to the [stream] where its subscribers can react to the messages. 20 * sent to the [stream] where its subscribers can react to the messages.
21 */ 21 */
22 class MessageBox { 22 class MessageBox {
23 final IsolateStream stream; 23 final IsolateStream stream;
24 final IsolateSink sink; 24 final IsolateSink sink;
25 25
26 MessageBox.oneShot() : this._oneShot(new ReceivePort()); 26 external MessageBox.oneShot();
27 MessageBox._oneShot(ReceivePort receivePort) 27 external MessageBox();
28 : stream = new IsolateStream._fromOriginalReceivePortOneShot(receivePort),
29 sink = new IsolateSink._fromPort(receivePort.toSendPort());
30
31 MessageBox() : this._(new ReceivePort());
32 MessageBox._(ReceivePort receivePort)
33 : stream = new IsolateStream._fromOriginalReceivePort(receivePort),
34 sink = new IsolateSink._fromPort(receivePort.toSendPort());
35 } 28 }
36 29
37 // Used for mangling. 30 external bool _isCloseToken(var object);
38 const int _ISOLATE_STREAM_TOKEN = 132421119;
39
40 class _CloseToken {
41 /// This token is sent from [IsolateSink]s to [IsolateStream]s to ask them to
42 /// close themselves.
43 const _CloseToken();
44 }
45 31
46 /** 32 /**
47 * [IsolateStream]s, together with [IsolateSink]s, are the only means of 33 * [IsolateStream]s, together with [IsolateSink]s, are the only means of
48 * communication between isolates. Each IsolateStream has a corresponding 34 * communication between isolates. Each IsolateStream has a corresponding
49 * [IsolateSink]. Any message written into that sink will be delivered to 35 * [IsolateSink]. Any message written into that sink will be delivered to
50 * the stream and then dispatched to the stream's subscribers. 36 * the stream and then dispatched to the stream's subscribers.
51 */ 37 */
52 class IsolateStream extends Stream<dynamic> { 38 class IsolateStream extends Stream<dynamic> {
53 bool _isClosed = false; 39 bool _isClosed = false;
54 final ReceivePort _port; 40 final ReceivePort _port;
55 StreamController _controller = new StreamController.broadcast(); 41 StreamController _controller = new StreamController.broadcast();
56 42
57 IsolateStream._fromOriginalReceivePort(this._port) { 43 IsolateStream._fromOriginalReceivePort(this._port) {
58 _port.receive((message, replyTo) { 44 _port.receive((message, replyTo) {
59 assert(replyTo == null); 45 assert(replyTo == null);
60 _add(message); 46 _add(message);
61 }); 47 });
62 } 48 }
63 49
64 IsolateStream._fromOriginalReceivePortOneShot(this._port) { 50 IsolateStream._fromOriginalReceivePortOneShot(this._port) {
65 _port.receive((message, replyTo) { 51 _port.receive((message, replyTo) {
66 assert(replyTo == null); 52 assert(replyTo == null);
67 _add(message); 53 _add(message);
68 close(); 54 close();
69 }); 55 });
70 } 56 }
71 57
72 void _add(var message) { 58 void _add(var message) {
73 message = _unmangleMessage(message); 59 if (_isCloseToken(message)) {
74 if (identical(message, const _CloseToken())) {
75 close(); 60 close();
76 } else { 61 } else {
77 _controller.sink.add(message); 62 _controller.sink.add(message);
78 } 63 }
79 } 64 }
80 65
81 /** 66 /**
82 * Close the stream from the receiving end. 67 * Close the stream from the receiving end.
83 * 68 *
84 * Closing an already closed port has no effect. 69 * Closing an already closed port has no effect.
85 */ 70 */
86 void close() { 71 void close() {
87 if (!_isClosed) { 72 if (!_isClosed) {
88 _isClosed = true; 73 _isClosed = true;
89 _port.close(); 74 _port.close();
90 _controller.close(); 75 _controller.close();
91 } 76 }
92 } 77 }
93 78
94 StreamSubscription listen(void onData(event), 79 StreamSubscription listen(void onData(event),
95 { void onError(AsyncError error), 80 { void onError(AsyncError error),
96 void onDone(), 81 void onDone(),
97 bool unsubscribeOnError}) { 82 bool unsubscribeOnError}) {
98 return _controller.stream.listen(onData, 83 return _controller.stream.listen(onData,
99 onError: onError, 84 onError: onError,
100 onDone: onDone, 85 onDone: onDone,
101 unsubscribeOnError: unsubscribeOnError); 86 unsubscribeOnError: unsubscribeOnError);
102 } 87 }
103
104 dynamic _unmangleMessage(var message) {
105 _IsolateDecoder decoder = new _IsolateDecoder(
106 _ISOLATE_STREAM_TOKEN,
107 (data) {
108 if (data is! List) return data;
109 if (data.length == 2 && data[0] == "Sink" && data[1] is SendPort) {
110 return new IsolateSink._fromPort(data[1]);
111 }
112 if (data.length == 1 && data[0] == "Close") {
113 return const _CloseToken();
114 }
115 return data;
116 });
117 return decoder.decode(message);
118 }
119 } 88 }
120 89
121 /** 90 /**
122 * [IsolateSink]s represent the feed for [IsolateStream]s. Any message written 91 * [IsolateSink]s represent the feed for [IsolateStream]s. Any message written
123 * to [this] is delivered to its respective [IsolateStream]. [IsolateSink]s are 92 * to [this] is delivered to its respective [IsolateStream]. [IsolateSink]s are
124 * created by [MessageBox]es. 93 * created by [MessageBox]es.
125 * 94 *
126 * [IsolateSink]s can be transmitted to other isolates. 95 * [IsolateSink]s can be transmitted to other isolates.
127 */ 96 */
128 class IsolateSink extends StreamSink<dynamic> { 97 abstract class IsolateSink extends StreamSink<dynamic> {
129 // TODO(8997): Implement EventSink instead. 98 // TODO(8997): Implement EventSink instead.
130 bool _isClosed = false; 99 // TODO(floitsch): Actually it should be a StreamSink (being able to flow-
131 final SendPort _port; 100 // control).
132 IsolateSink._fromPort(this._port);
133 101
134 /** 102 /**
135 * Sends an asynchronous [message] to the linked [IsolateStream]. The message 103 * Sends an asynchronous [message] to the linked [IsolateStream]. The message
136 * is copied to the receiving isolate. 104 * is copied to the receiving isolate.
137 * 105 *
138 * The content of [message] can be: primitive values (null, num, bool, double, 106 * The content of [message] can be: primitive values (null, num, bool, double,
139 * String), instances of [IsolateSink]s, and lists and maps whose elements are 107 * String), instances of [IsolateSink]s, and lists and maps whose elements are
140 * any of these. List and maps are also allowed to be cyclic. 108 * any of these. List and maps are also allowed to be cyclic.
141 * 109 *
142 * In the special circumstances when two isolates share the same code and are 110 * In the special circumstances when two isolates share the same code and are
143 * running in the same process (e.g. isolates created via [spawnFunction]), it 111 * running in the same process (e.g. isolates created via [spawnFunction]), it
144 * is also possible to send object instances (which would be copied in the 112 * is also possible to send object instances (which would be copied in the
145 * process). This is currently only supported by the dartvm. For now, the 113 * process). This is currently only supported by the dartvm. For now, the
146 * dart2js compiler only supports the restricted messages described above. 114 * dart2js compiler only supports the restricted messages described above.
147 */ 115 */
148 void add(dynamic message) { 116 void add(dynamic message);
149 var mangled = _mangleMessage(message);
150 _port.send(mangled);
151 }
152 117
153 void addError(AsyncError errorEvent) { 118 void addError(AsyncError errorEvent);
154 throw new UnimplementedError("signalError on isolate streams");
155 }
156 119
157 dynamic _mangleMessage(var message) { 120 /** Closing multiple times is allowed. */
158 _IsolateEncoder encoder = new _IsolateEncoder( 121 void close();
159 _ISOLATE_STREAM_TOKEN,
160 (data) {
161 if (data is IsolateSink) return ["Sink", data._port];
162 if (identical(data, const _CloseToken())) return ["Close"];
163 return data;
164 });
165 return encoder.encode(message);
166 }
167
168 void close() {
169 if (_isClosed) throw new StateError("Sending on closed stream");
170 add(const _CloseToken());
171 _isClosed = true;
172 }
173 122
174 /** 123 /**
175 * Tests whether [other] is an [IsolateSink] feeding into the same 124 * Tests whether [other] is an [IsolateSink] feeding into the same
176 * [IsolateStream] as this one. 125 * [IsolateStream] as this one.
177 */ 126 */
178 bool operator==(var other) { 127 bool operator==(var other);
179 return other is IsolateSink && _port == other._port;
180 }
181
182 int get hashCode => _port.hashCode + 499;
183 } 128 }
184 129
185 130
186 /** 131 /**
187 * Creates and spawns an isolate that shares the same code as the current 132 * Creates and spawns an isolate that shares the same code as the current
188 * isolate, but that starts from [topLevelFunction]. The [topLevelFunction] 133 * isolate, but that starts from [topLevelFunction]. The [topLevelFunction]
189 * argument must be a static top-level function or a static method that takes no 134 * argument must be a static top-level function or a static method that takes no
190 * arguments. 135 * arguments.
191 * 136 *
192 * When any isolate starts (even the main script of the application), a default 137 * When any isolate starts (even the main script of the application), a default
193 * [IsolateStream] is created for it. This sink is available from the top-level 138 * [IsolateStream] is created for it. This sink is available from the top-level
194 * getter [stream] defined in this library. 139 * getter [stream] defined in this library.
195 * 140 *
196 * [spawnFunction] returns an [IsolateSink] feeding into the child isolate's 141 * [spawnFunction] returns an [IsolateSink] feeding into the child isolate's
197 * default stream. 142 * default stream.
198 * 143 *
199 * The optional [unhandledExceptionCallback] argument is invoked whenever an 144 * The optional [unhandledExceptionCallback] argument is invoked whenever an
200 * exception inside the isolate is unhandled. It can be seen as a big 145 * exception inside the isolate is unhandled. It can be seen as a big
201 * `try/catch` around everything that is executed inside the isolate. The 146 * `try/catch` around everything that is executed inside the isolate. The
202 * callback should return `true` when it was able to handled the exception. 147 * callback should return `true` when it was able to handled the exception.
203 * 148 *
204 * See comments at the top of this library for more details. 149 * See comments at the top of this library for more details.
205 */ 150 */
206 IsolateSink streamSpawnFunction( 151 external IsolateSink streamSpawnFunction(
207 void topLevelFunction(), 152 void topLevelFunction(),
208 [bool unhandledExceptionCallback(IsolateUnhandledException e)]) { 153 [bool unhandledExceptionCallback(IsolateUnhandledException e)]);
209 SendPort sendPort = spawnFunction(topLevelFunction,
210 unhandledExceptionCallback);
211 return new IsolateSink._fromPort(sendPort);
212 }
213
214 /**
215 * Creates and spawns an isolate whose code is available at [uri]. Like with
216 * [streamSpawnFunction], the child isolate will have a default [IsolateStream],
217 * and a this function returns an [IsolateSink] feeding into it.
218 *
219 * See comments at the top of this library for more details.
220 */
221 IsolateSink streamSpawnUri(String uri) {
222 SendPort sendPort = spawnUri(uri);
223 return new IsolateSink._fromPort(sendPort);
224 }
OLDNEW
« no previous file with comments | « sdk/lib/isolate/isolate_sources.gypi ('k') | sdk/lib/isolate/mangler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698