OLD | NEW |
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 /** Common functionality to all send ports. */ | 5 /** Common functionality to all send ports. */ |
6 class _BaseSendPort implements SendPort { | 6 class _BaseSendPort implements SendPort { |
7 /** Id for the destination isolate. */ | 7 /** Id for the destination isolate. */ |
8 final int _isolateId; | 8 final int _isolateId; |
9 | 9 |
10 _BaseSendPort(this._isolateId); | 10 _BaseSendPort(this._isolateId); |
11 | 11 |
12 _ReceivePortSingleShotImpl call(var message) { | |
13 final result = new _ReceivePortSingleShotImpl(); | |
14 this.send(message, result.toSendPort()); | |
15 return result; | |
16 } | |
17 | |
18 static void checkReplyTo(SendPort replyTo) { | 12 static void checkReplyTo(SendPort replyTo) { |
19 if (replyTo !== null | 13 if (replyTo !== null |
20 && replyTo is! _NativeJsSendPort | 14 && replyTo is! _NativeJsSendPort |
21 && replyTo is! _WorkerSendPort | 15 && replyTo is! _WorkerSendPort |
22 && replyTo is! _BufferingSendPort) { | 16 && replyTo is! _BufferingSendPort) { |
23 throw new Exception("SendPort.send: Illegal replyTo port type"); | 17 throw new Exception("SendPort.send: Illegal replyTo port type"); |
24 } | 18 } |
25 } | 19 } |
26 | 20 |
27 // TODO(sigmund): replace the current SendPort.call with the following: | 21 Future call(var message) { |
28 //Future call(var message) { | 22 final completer = new Completer(); |
29 // final completer = new Completer(); | 23 final port = new _ReceivePortImpl(); |
30 // final port = new _ReceivePort.singleShot(); | 24 send(message, port.toSendPort()); |
31 // send(message, port.toSendPort()); | 25 port.receive((value, ignoreReplyTo) { |
32 // port.receive((value, ignoreReplyTo) { | 26 port.close(); |
33 // if (value is Exception) { | 27 if (value is Exception) { |
34 // completer.completeException(value); | 28 completer.completeException(value); |
35 // } else { | 29 } else { |
36 // completer.complete(value); | 30 completer.complete(value); |
37 // } | 31 } |
38 // }); | 32 }); |
39 // return completer.future; | 33 return completer.future; |
40 //} | 34 } |
41 | 35 |
42 abstract void send(var message, [SendPort replyTo]); | 36 abstract void send(var message, [SendPort replyTo]); |
43 abstract bool operator ==(var other); | 37 abstract bool operator ==(var other); |
44 abstract int hashCode(); | 38 abstract int hashCode(); |
45 } | 39 } |
46 | 40 |
47 /** A send port that delivers messages in-memory via native JavaScript calls. */ | 41 /** A send port that delivers messages in-memory via native JavaScript calls. */ |
48 class _NativeJsSendPort extends _BaseSendPort implements SendPort { | 42 class _NativeJsSendPort extends _BaseSendPort implements SendPort { |
49 final _ReceivePortImpl _receivePort; | 43 final _ReceivePortImpl _receivePort; |
50 | 44 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 int hashCode() => _id; | 174 int hashCode() => _id; |
181 } | 175 } |
182 | 176 |
183 /** Default factory for receive ports. */ | 177 /** Default factory for receive ports. */ |
184 class _ReceivePortFactory { | 178 class _ReceivePortFactory { |
185 | 179 |
186 factory ReceivePort() { | 180 factory ReceivePort() { |
187 return new _ReceivePortImpl(); | 181 return new _ReceivePortImpl(); |
188 } | 182 } |
189 | 183 |
190 factory ReceivePort.singleShot() { | |
191 return new _ReceivePortSingleShotImpl(); | |
192 } | |
193 } | 184 } |
194 | 185 |
195 /** Implementation of a multi-use [ReceivePort] on top of JavaScript. */ | 186 /** Implementation of a multi-use [ReceivePort] on top of JavaScript. */ |
196 class _ReceivePortImpl implements ReceivePort { | 187 class _ReceivePortImpl implements ReceivePort { |
197 int _id; | 188 int _id; |
198 Function _callback; | 189 Function _callback; |
199 static int _nextFreeId = 1; | 190 static int _nextFreeId = 1; |
200 | 191 |
201 _ReceivePortImpl() | 192 _ReceivePortImpl() |
202 : _id = _nextFreeId++ { | 193 : _id = _nextFreeId++ { |
203 _globalState.currentContext.register(_id, this); | 194 _globalState.currentContext.register(_id, this); |
204 } | 195 } |
205 | 196 |
206 void receive(void onMessage(var message, SendPort replyTo)) { | 197 void receive(void onMessage(var message, SendPort replyTo)) { |
207 _callback = onMessage; | 198 _callback = onMessage; |
208 } | 199 } |
209 | 200 |
210 void close() { | 201 void close() { |
211 _callback = null; | 202 _callback = null; |
212 _globalState.currentContext.unregister(_id); | 203 _globalState.currentContext.unregister(_id); |
213 } | 204 } |
214 | 205 |
215 SendPort toSendPort() { | 206 SendPort toSendPort() { |
216 return new _NativeJsSendPort(this, _globalState.currentContext.id); | 207 return new _NativeJsSendPort(this, _globalState.currentContext.id); |
217 } | 208 } |
218 } | 209 } |
219 | 210 |
220 /** Implementation of a single-shot [ReceivePort]. */ | |
221 class _ReceivePortSingleShotImpl implements ReceivePort { | |
222 | |
223 _ReceivePortSingleShotImpl() : _port = new _ReceivePortImpl() { } | |
224 | |
225 void receive(void callback(var message, SendPort replyTo)) { | |
226 _port.receive((var message, SendPort replyTo) { | |
227 _port.close(); | |
228 callback(message, replyTo); | |
229 }); | |
230 } | |
231 | |
232 void close() { | |
233 _port.close(); | |
234 } | |
235 | |
236 SendPort toSendPort() => _port.toSendPort(); | |
237 | |
238 final _ReceivePortImpl _port; | |
239 } | |
240 | |
241 /** Wait until all ports in a message are resolved. */ | 211 /** Wait until all ports in a message are resolved. */ |
242 _waitForPendingPorts(var message, void callback()) { | 212 _waitForPendingPorts(var message, void callback()) { |
243 final finder = new _PendingSendPortFinder(); | 213 final finder = new _PendingSendPortFinder(); |
244 finder.traverse(message); | 214 finder.traverse(message); |
245 Futures.wait(finder.ports).then((_) => callback()); | 215 Futures.wait(finder.ports).then((_) => callback()); |
246 } | 216 } |
247 | 217 |
248 | 218 |
249 /** Visitor that finds all unresolved [SendPort]s in a message. */ | 219 /** Visitor that finds all unresolved [SendPort]s in a message. */ |
250 class _PendingSendPortFinder extends _MessageTraverser { | 220 class _PendingSendPortFinder extends _MessageTraverser { |
251 List<Future<SendPort>> ports; | 221 List<Future<SendPort>> ports; |
252 _PendingSendPortFinder() : super(), ports = []; | 222 _PendingSendPortFinder() : super(), ports = []; |
253 | 223 |
254 visitPrimitive(x) {} | 224 visitPrimitive(x) {} |
255 visitNativeJsSendPort(_NativeJsSendPort port) {} | 225 visitNativeJsSendPort(_NativeJsSendPort port) {} |
256 visitWorkerSendPort(_WorkerSendPort port) {} | 226 visitWorkerSendPort(_WorkerSendPort port) {} |
257 visitReceivePort(_ReceivePortImpl port) {} | |
258 visitReceivePortSingleShot(_ReceivePortSingleShotImpl port) {} | |
259 | 227 |
260 visitList(List list) { | 228 visitList(List list) { |
261 final visited = _getInfo(list); | 229 final visited = _getInfo(list); |
262 if (visited !== null) return; | 230 if (visited !== null) return; |
263 _attachInfo(list, true); | 231 _attachInfo(list, true); |
264 // TODO(sigmund): replace with the following: (bug #1660) | 232 // TODO(sigmund): replace with the following: (bug #1660) |
265 // list.forEach(_dispatch); | 233 // list.forEach(_dispatch); |
266 list.forEach((e) => _dispatch(e)); | 234 list.forEach((e) => _dispatch(e)); |
267 } | 235 } |
268 | 236 |
269 visitMap(Map map) { | 237 visitMap(Map map) { |
270 final visited = _getInfo(map); | 238 final visited = _getInfo(map); |
271 if (visited !== null) return; | 239 if (visited !== null) return; |
272 | 240 |
273 _attachInfo(map, true); | 241 _attachInfo(map, true); |
274 // TODO(sigmund): replace with the following: (bug #1660) | 242 // TODO(sigmund): replace with the following: (bug #1660) |
275 // map.getValues().forEach(_dispatch); | 243 // map.getValues().forEach(_dispatch); |
276 map.getValues().forEach((e) => _dispatch(e)); | 244 map.getValues().forEach((e) => _dispatch(e)); |
277 } | 245 } |
278 | 246 |
279 visitBufferingSendPort(_BufferingSendPort port) { | 247 visitBufferingSendPort(_BufferingSendPort port) { |
280 if (port._port == null) { | 248 if (port._port == null) { |
281 ports.add(port._futurePort); | 249 ports.add(port._futurePort); |
282 } | 250 } |
283 } | 251 } |
284 } | 252 } |
OLD | NEW |