| 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 import "dart:collection" show HashMap; | 5 import "dart:collection" show HashMap; |
| 6 | 6 |
| 7 patch class ReceivePort { | 7 patch class ReceivePort { |
| 8 /* patch */ factory ReceivePort() = _ReceivePortImpl; | 8 /* patch */ factory ReceivePort() = _ReceivePortImpl; |
| 9 | 9 |
| 10 /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) = | 10 /* patch */ factory ReceivePort.fromRawReceivePort(RawReceivePort rawPort) = |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 /// The callback that has been registered through `scheduleImmediate`. | 70 /// The callback that has been registered through `scheduleImmediate`. |
| 71 ImmediateCallback _pendingImmediateCallback; | 71 ImmediateCallback _pendingImmediateCallback; |
| 72 | 72 |
| 73 /// The closure that should be used as scheduleImmediateClosure, when the VM | 73 /// The closure that should be used as scheduleImmediateClosure, when the VM |
| 74 /// is responsible for the event loop. | 74 /// is responsible for the event loop. |
| 75 void _isolateScheduleImmediate(void callback()) { | 75 void _isolateScheduleImmediate(void callback()) { |
| 76 assert(_pendingImmediateCallback == null); | 76 assert(_pendingImmediateCallback == null); |
| 77 _pendingImmediateCallback = callback; | 77 _pendingImmediateCallback = callback; |
| 78 } | 78 } |
| 79 | 79 |
| 80 void _runPendingImmediateCallback() { |
| 81 if (_pendingImmediateCallback != null) { |
| 82 var callback = _pendingImmediateCallback; |
| 83 _pendingImmediateCallback = null; |
| 84 callback(); |
| 85 } |
| 86 } |
| 87 |
| 80 /// The embedder can execute this function to get hold of | 88 /// The embedder can execute this function to get hold of |
| 81 /// [_isolateScheduleImmediate] above. | 89 /// [_isolateScheduleImmediate] above. |
| 82 Function _getIsolateScheduleImmediateClosure() { | 90 Function _getIsolateScheduleImmediateClosure() { |
| 83 return _isolateScheduleImmediate; | 91 return _isolateScheduleImmediate; |
| 84 } | 92 } |
| 85 | 93 |
| 86 class _RawReceivePortImpl implements RawReceivePort { | 94 class _RawReceivePortImpl implements RawReceivePort { |
| 87 factory _RawReceivePortImpl() native "RawReceivePortImpl_factory"; | 95 factory _RawReceivePortImpl() native "RawReceivePortImpl_factory"; |
| 88 | 96 |
| 89 close() { | 97 close() { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 113 var result = _handlerMap[id]; | 121 var result = _handlerMap[id]; |
| 114 return result; | 122 return result; |
| 115 } | 123 } |
| 116 | 124 |
| 117 // Called from the VM to dispatch to the handler. | 125 // Called from the VM to dispatch to the handler. |
| 118 static void _handleMessage(Function handler, var message) { | 126 static void _handleMessage(Function handler, var message) { |
| 119 // TODO(floitsch): this relies on the fact that any exception aborts the | 127 // TODO(floitsch): this relies on the fact that any exception aborts the |
| 120 // VM. Once we have non-fatal global exceptions we need to catch errors | 128 // VM. Once we have non-fatal global exceptions we need to catch errors |
| 121 // so that we can run the immediate callbacks. | 129 // so that we can run the immediate callbacks. |
| 122 handler(message); | 130 handler(message); |
| 123 if (_pendingImmediateCallback != null) { | 131 _runPendingImmediateCallback(); |
| 124 var callback = _pendingImmediateCallback; | |
| 125 _pendingImmediateCallback = null; | |
| 126 callback(); | |
| 127 } | |
| 128 } | 132 } |
| 129 | 133 |
| 130 // Call into the VM to close the VM maintained mappings. | 134 // Call into the VM to close the VM maintained mappings. |
| 131 _closeInternal() native "RawReceivePortImpl_closeInternal"; | 135 _closeInternal() native "RawReceivePortImpl_closeInternal"; |
| 132 | 136 |
| 133 void set handler(Function value) { | 137 void set handler(Function value) { |
| 134 _handlerMap[this._get_id()] = value; | 138 _handlerMap[this._get_id()] = value; |
| 135 } | 139 } |
| 136 | 140 |
| 137 // TODO(iposva): Ideally keep this map in the VM. | 141 // TODO(iposva): Ideally keep this map in the VM. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 typedef _MainFunction(); | 178 typedef _MainFunction(); |
| 175 typedef _MainFunctionArgs(args); | 179 typedef _MainFunctionArgs(args); |
| 176 typedef _MainFunctionArgsMessage(args, message); | 180 typedef _MainFunctionArgsMessage(args, message); |
| 177 | 181 |
| 178 /** | 182 /** |
| 179 * Takes the real entry point as argument and invokes it with the initial | 183 * Takes the real entry point as argument and invokes it with the initial |
| 180 * message. | 184 * message. |
| 181 * | 185 * |
| 182 * The initial startup message is received through the control port. | 186 * The initial startup message is received through the control port. |
| 183 */ | 187 */ |
| 184 void _startIsolate(Function entryPoint, bool isSpawnUri) { | 188 void _startIsolate(SendPort parentPort, |
| 185 // This port keeps the isolate alive until the initial startup message has | 189 Function entryPoint, |
| 186 // been received. | 190 List<String> args, |
| 187 var keepAlivePort = new RawReceivePort(); | 191 var message, |
| 192 bool isSpawnUri, |
| 193 RawReceivePort controlPort, |
| 194 List capabilities) { |
| 195 if (controlPort != null) { |
| 196 controlPort.handler = (_) {}; // Nobody home on the control port. |
| 197 } |
| 198 if (parentPort != null) { |
| 199 // Build a message to our parent isolate providing access to the |
| 200 // current isolate's control port and capabilities. |
| 201 // |
| 202 // TODO(floitsch): Send an error message if we can't find the entry point. |
| 203 var readyMessage = new List(2); |
| 204 readyMessage[0] = controlPort.sendPort; |
| 205 readyMessage[1] = capabilities; |
| 188 | 206 |
| 189 ignoreHandler(message) { | 207 // Out of an excess of paranoia we clear the capabilities from the |
| 190 // Messages on the current Isolate's control port are dropped after the | 208 // stack. Not really necessary. |
| 191 // initial startup message has been received. | 209 capabilities = null; |
| 210 parentPort.send(readyMessage); |
| 192 } | 211 } |
| 212 assert(capabilities == null); |
| 193 | 213 |
| 194 isolateStartHandler(message) { | 214 if (isSpawnUri) { |
| 195 // We received the initial startup message. Ignore all further messages and | 215 if (entryPoint is _MainFunctionArgsMessage) { |
| 196 // close the port which kept this isolate alive. | 216 entryPoint(args, message); |
| 197 Isolate._self.handler = ignoreHandler; | 217 } else if (entryPoint is _MainFunctionArgs) { |
| 198 keepAlivePort.close(); | 218 entryPoint(args); |
| 199 | 219 } else { |
| 200 SendPort replyTo = message[0]; | 220 entryPoint(); |
| 201 if (replyTo != null) { | |
| 202 // TODO(floitsch): don't send ok-message if we can't find the entry point. | |
| 203 replyTo.send("started"); | |
| 204 } | 221 } |
| 205 if (isSpawnUri) { | 222 } else { |
| 206 assert(message.length == 3); | 223 entryPoint(message); |
| 207 List<String> args = message[1]; | |
| 208 var isolateMessage = message[2]; | |
| 209 if (entryPoint is _MainFunctionArgsMessage) { | |
| 210 entryPoint(args, isolateMessage); | |
| 211 } else if (entryPoint is _MainFunctionArgs) { | |
| 212 entryPoint(args); | |
| 213 } else { | |
| 214 entryPoint(); | |
| 215 } | |
| 216 } else { | |
| 217 assert(message.length == 2); | |
| 218 var entryMessage = message[1]; | |
| 219 entryPoint(entryMessage); | |
| 220 } | |
| 221 } | 224 } |
| 222 | 225 _runPendingImmediateCallback(); |
| 223 Isolate._self.handler = isolateStartHandler; | |
| 224 } | 226 } |
| 225 | 227 |
| 226 patch class Isolate { | 228 patch class Isolate { |
| 227 /* patch */ static Future<Isolate> spawn( | 229 /* patch */ static Future<Isolate> spawn( |
| 228 void entryPoint(message), var message, { bool paused: false }) { | 230 void entryPoint(message), var message, { bool paused: false }) { |
| 229 // `paused` isn't handled yet. | 231 // `paused` isn't handled yet. |
| 232 RawReceivePort readyPort; |
| 230 try { | 233 try { |
| 231 // The VM will invoke [_startIsolate] with entryPoint as argument. | 234 // The VM will invoke [_startIsolate] with entryPoint as argument. |
| 232 List spawnData = _spawnFunction(entryPoint); | 235 readyPort = new RawReceivePort(); |
| 233 assert(spawnData.length == 3); | 236 _spawnFunction(readyPort.sendPort, entryPoint, message); |
| 234 SendPort controlPort = spawnData[0]; | |
| 235 RawReceivePort readyPort = new RawReceivePort(); | |
| 236 controlPort.send([readyPort.sendPort, message]); | |
| 237 Completer completer = new Completer<Isolate>.sync(); | 237 Completer completer = new Completer<Isolate>.sync(); |
| 238 readyPort.handler = (readyMessage) { | 238 readyPort.handler = (readyMessage) { |
| 239 assert(readyMessage == 'started'); | |
| 240 readyPort.close(); | 239 readyPort.close(); |
| 240 assert(readyMessage is List); |
| 241 assert(readyMessage.length == 2); |
| 242 SendPort controlPort = readyMessage[0]; |
| 243 List capabilities = readyMessage[1]; |
| 241 completer.complete(new Isolate(controlPort, | 244 completer.complete(new Isolate(controlPort, |
| 242 pauseCapability: spawnData[1], | 245 pauseCapability: capabilities[0], |
| 243 terminateCapability: spawnData[2])); | 246 terminateCapability: capabilities[1])); |
| 244 }; | 247 }; |
| 245 return completer.future; | 248 return completer.future; |
| 246 } catch (e, st) { | 249 } catch (e, st) { |
| 250 if (readyPort != null) { |
| 251 readyPort.close(); |
| 252 } |
| 247 return new Future<Isolate>.error(e, st); | 253 return new Future<Isolate>.error(e, st); |
| 248 }; | 254 }; |
| 249 } | 255 } |
| 250 | 256 |
| 251 /* patch */ static Future<Isolate> spawnUri( | 257 /* patch */ static Future<Isolate> spawnUri( |
| 252 Uri uri, List<String> args, var message, { bool paused: false }) { | 258 Uri uri, List<String> args, var message, { bool paused: false }) { |
| 253 // `paused` isn't handled yet. | 259 // `paused` isn't handled yet. |
| 260 RawReceivePort readyPort; |
| 254 try { | 261 try { |
| 255 // The VM will invoke [_startIsolate] and not `main`. | 262 // The VM will invoke [_startIsolate] and not `main`. |
| 256 List spawnData = _spawnUri(uri.toString()); | 263 readyPort = new RawReceivePort(); |
| 257 assert(spawnData.length == 3); | 264 _spawnUri(readyPort.sendPort, uri.toString(), args, message); |
| 258 SendPort controlPort = spawnData[0]; | |
| 259 RawReceivePort readyPort = new RawReceivePort(); | |
| 260 controlPort.send([readyPort.sendPort, args, message]); | |
| 261 Completer completer = new Completer<Isolate>.sync(); | 265 Completer completer = new Completer<Isolate>.sync(); |
| 262 readyPort.handler = (readyMessage) { | 266 readyPort.handler = (readyMessage) { |
| 263 assert(readyMessage == 'started'); | |
| 264 readyPort.close(); | 267 readyPort.close(); |
| 268 assert(readyMessage is List); |
| 269 assert(readyMessage.length == 2); |
| 270 SendPort controlPort = readyMessage[0]; |
| 271 List capabilities = readyMessage[1]; |
| 265 completer.complete(new Isolate(controlPort, | 272 completer.complete(new Isolate(controlPort, |
| 266 pauseCapability: spawnData[1], | 273 pauseCapability: capabilities[0], |
| 267 terminateCapability: spawnData[2])); | 274 terminateCapability: capabilities[1])); |
| 268 }; | 275 }; |
| 269 return completer.future; | 276 return completer.future; |
| 270 } catch (e, st) { | 277 } catch (e, st) { |
| 278 if (readyPort != null) { |
| 279 readyPort.close(); |
| 280 } |
| 271 return new Future<Isolate>.error(e, st); | 281 return new Future<Isolate>.error(e, st); |
| 272 }; | 282 }; |
| 273 return completer.future; | 283 return completer.future; |
| 274 } | 284 } |
| 275 | 285 |
| 276 static final RawReceivePort _self = _mainPort; | |
| 277 static RawReceivePort get _mainPort native "Isolate_mainPort"; | |
| 278 | |
| 279 // TODO(iposva): Cleanup to have only one definition. | 286 // TODO(iposva): Cleanup to have only one definition. |
| 280 // These values need to be kept in sync with the class IsolateMessageHandler | 287 // These values need to be kept in sync with the class IsolateMessageHandler |
| 281 // in vm/isolate.cc. | 288 // in vm/isolate.cc. |
| 282 static const _PAUSE = 1; | 289 static const _PAUSE = 1; |
| 283 static const _RESUME = 2; | 290 static const _RESUME = 2; |
| 284 | 291 |
| 285 static List _spawnFunction(Function topLevelFunction) | 292 static SendPort _spawnFunction(SendPort readyPort, Function topLevelFunction, |
| 293 var message) |
| 286 native "Isolate_spawnFunction"; | 294 native "Isolate_spawnFunction"; |
| 287 | 295 |
| 288 static List _spawnUri(String uri) native "Isolate_spawnUri"; | 296 static SendPort _spawnUri(SendPort readyPort, String uri, |
| 297 List<String> args, var message) |
| 298 native "Isolate_spawnUri"; |
| 289 | 299 |
| 290 static void _sendOOB(port, msg) native "Isolate_sendOOB"; | 300 static void _sendOOB(port, msg) native "Isolate_sendOOB"; |
| 291 | 301 |
| 292 /* patch */ void _pause(Capability resumeCapability) { | 302 /* patch */ void _pause(Capability resumeCapability) { |
| 293 var msg = new List(4) | 303 var msg = new List(4) |
| 294 ..[0] = 0 // Make room for OOM message type. | 304 ..[0] = 0 // Make room for OOM message type. |
| 295 ..[1] = _PAUSE | 305 ..[1] = _PAUSE |
| 296 ..[2] = pauseCapability | 306 ..[2] = pauseCapability |
| 297 ..[3] = resumeCapability; | 307 ..[3] = resumeCapability; |
| 298 _sendOOB(controlPort, msg); | 308 _sendOOB(controlPort, msg); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 328 } | 338 } |
| 329 | 339 |
| 330 /* patch */ void addErrorListener(SendPort port) { | 340 /* patch */ void addErrorListener(SendPort port) { |
| 331 throw new UnsupportedError("addErrorListener"); | 341 throw new UnsupportedError("addErrorListener"); |
| 332 } | 342 } |
| 333 | 343 |
| 334 /* patch */ void removeErrorListener(SendPort port) { | 344 /* patch */ void removeErrorListener(SendPort port) { |
| 335 throw new UnsupportedError("removeErrorListener"); | 345 throw new UnsupportedError("removeErrorListener"); |
| 336 } | 346 } |
| 337 } | 347 } |
| OLD | NEW |