| 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 library _isolate_helper; | 5 library _isolate_helper; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection' show Queue, HashMap; | 8 import 'dart:collection' show Queue, HashMap; |
| 9 import 'dart:isolate'; | 9 import 'dart:isolate'; |
| 10 import 'dart:_js_helper' show convertDartClosureToJS, | 10 import 'dart:_js_helper' show convertDartClosureToJS, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 _IsolateContext _currentIsolate() => _globalState.currentContext; | 66 _IsolateContext _currentIsolate() => _globalState.currentContext; |
| 67 | 67 |
| 68 /** | 68 /** |
| 69 * Wrapper that takes the dart entry point and runs it within an isolate. The | 69 * Wrapper that takes the dart entry point and runs it within an isolate. The |
| 70 * dart2js compiler will inject a call of the form | 70 * dart2js compiler will inject a call of the form |
| 71 * [: startRootIsolate(main); :] when it determines that this wrapping | 71 * [: startRootIsolate(main); :] when it determines that this wrapping |
| 72 * is needed. For single-isolate applications (e.g. hello world), this | 72 * is needed. For single-isolate applications (e.g. hello world), this |
| 73 * call is not emitted. | 73 * call is not emitted. |
| 74 */ | 74 */ |
| 75 void startRootIsolate(entry) { | 75 void startRootIsolate(entry) { |
| 76 _globalState = new _Manager(); | 76 _globalState = new _Manager(entry); |
| 77 | 77 |
| 78 // Don't start the main loop again, if we are in a worker. | 78 // Don't start the main loop again, if we are in a worker. |
| 79 if (_globalState.isWorker) return; | 79 if (_globalState.isWorker) return; |
| 80 final rootContext = new _IsolateContext(); | 80 final rootContext = new _IsolateContext(); |
| 81 _globalState.rootContext = rootContext; | 81 _globalState.rootContext = rootContext; |
| 82 | 82 |
| 83 // BUG(5151491): Setting currentContext should not be necessary, but | 83 // BUG(5151491): Setting currentContext should not be necessary, but |
| 84 // because closures passed to the DOM as event handlers do not bind their | 84 // because closures passed to the DOM as event handlers do not bind their |
| 85 // isolate automatically we try to give them a reasonable context to live in | 85 // isolate automatically we try to give them a reasonable context to live in |
| 86 // by having a "default" isolate (the first one created). | 86 // by having a "default" isolate (the first one created). |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 * dead, but DOM callbacks could resurrect it. | 181 * dead, but DOM callbacks could resurrect it. |
| 182 */ | 182 */ |
| 183 Map<int, _IsolateContext> isolates; | 183 Map<int, _IsolateContext> isolates; |
| 184 | 184 |
| 185 /** Reference to the main [_Manager]. Null in the main [_Manager] itself. */ | 185 /** Reference to the main [_Manager]. Null in the main [_Manager] itself. */ |
| 186 _ManagerStub mainManager; | 186 _ManagerStub mainManager; |
| 187 | 187 |
| 188 /** Registry of active [_ManagerStub]s. Only used in the main [_Manager]. */ | 188 /** Registry of active [_ManagerStub]s. Only used in the main [_Manager]. */ |
| 189 Map<int, _ManagerStub> managers; | 189 Map<int, _ManagerStub> managers; |
| 190 | 190 |
| 191 _Manager() { | 191 /** The entry point given by [startRootIsolate]. */ |
| 192 final Function entry; |
| 193 |
| 194 _Manager(this.entry) { |
| 192 _nativeDetectEnvironment(); | 195 _nativeDetectEnvironment(); |
| 193 topEventLoop = new _EventLoop(); | 196 topEventLoop = new _EventLoop(); |
| 194 isolates = new Map<int, _IsolateContext>(); | 197 isolates = new Map<int, _IsolateContext>(); |
| 195 managers = new Map<int, _ManagerStub>(); | 198 managers = new Map<int, _ManagerStub>(); |
| 196 if (isWorker) { // "if we are not the main manager ourself" is the intent. | 199 if (isWorker) { // "if we are not the main manager ourself" is the intent. |
| 197 mainManager = new _MainManagerStub(); | 200 mainManager = new _MainManagerStub(); |
| 198 _nativeInitWorkerMessageHandler(); | 201 _nativeInitWorkerMessageHandler(); |
| 199 } | 202 } |
| 200 } | 203 } |
| 201 | 204 |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 | 500 |
| 498 /** | 501 /** |
| 499 * Process messages on a worker, either to control the worker instance or to | 502 * Process messages on a worker, either to control the worker instance or to |
| 500 * pass messages along to the isolate running in the worker. | 503 * pass messages along to the isolate running in the worker. |
| 501 */ | 504 */ |
| 502 static void _processWorkerMessage(sender, e) { | 505 static void _processWorkerMessage(sender, e) { |
| 503 var msg = _deserializeMessage(_getEventData(e)); | 506 var msg = _deserializeMessage(_getEventData(e)); |
| 504 switch (msg['command']) { | 507 switch (msg['command']) { |
| 505 case 'start': | 508 case 'start': |
| 506 _globalState.currentManagerId = msg['id']; | 509 _globalState.currentManagerId = msg['id']; |
| 507 Function entryPoint = _getJSFunctionFromName(msg['functionName']); | 510 String functionName = msg['functionName']; |
| 511 Function entryPoint = (functionName == null) |
| 512 ? _globalState.entry |
| 513 : _getJSFunctionFromName(functionName); |
| 508 var replyTo = _deserializeMessage(msg['replyTo']); | 514 var replyTo = _deserializeMessage(msg['replyTo']); |
| 509 var context = new _IsolateContext(); | 515 var context = new _IsolateContext(); |
| 510 _globalState.topEventLoop.enqueue(context, () { | 516 _globalState.topEventLoop.enqueue(context, () { |
| 511 _startIsolate(entryPoint, replyTo); | 517 _startIsolate(entryPoint, replyTo); |
| 512 }, 'worker-start'); | 518 }, 'worker-start'); |
| 513 // Make sure we always have a current context in this worker. | 519 // Make sure we always have a current context in this worker. |
| 514 // TODO(7907): This is currently needed because we're using | 520 // TODO(7907): This is currently needed because we're using |
| 515 // Timers to implement Futures, and this isolate library | 521 // Timers to implement Futures, and this isolate library |
| 516 // implementation uses Futures. We should either stop using | 522 // implementation uses Futures. We should either stop using |
| 517 // Futures in this library, or re-adapt if Futures get a | 523 // Futures in this library, or re-adapt if Futures get a |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 lazyPort = new ReceivePort(); | 667 lazyPort = new ReceivePort(); |
| 662 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort()); | 668 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort()); |
| 663 topLevel(); | 669 topLevel(); |
| 664 } | 670 } |
| 665 | 671 |
| 666 /** | 672 /** |
| 667 * Spawns an isolate in a worker. [factoryName] is the Javascript constructor | 673 * Spawns an isolate in a worker. [factoryName] is the Javascript constructor |
| 668 * name for the isolate entry point class. | 674 * name for the isolate entry point class. |
| 669 */ | 675 */ |
| 670 static void _spawnWorker(functionName, uri, replyPort) { | 676 static void _spawnWorker(functionName, uri, replyPort) { |
| 671 if (functionName == null) functionName = 'main'; | |
| 672 if (uri == null) uri = thisScript; | 677 if (uri == null) uri = thisScript; |
| 673 final worker = _newWorker(uri); | 678 final worker = _newWorker(uri); |
| 674 worker.onmessage = JS('', | 679 worker.onmessage = JS('', |
| 675 'function(e) { #(#, e); }', | 680 'function(e) { #(#, e); }', |
| 676 DART_CLOSURE_TO_JS(_processWorkerMessage), | 681 DART_CLOSURE_TO_JS(_processWorkerMessage), |
| 677 worker); | 682 worker); |
| 678 var workerId = _globalState.nextManagerId++; | 683 var workerId = _globalState.nextManagerId++; |
| 679 // We also store the id on the worker itself so that we can unregister it. | 684 // We also store the id on the worker itself so that we can unregister it. |
| 680 worker.id = workerId; | 685 worker.id = workerId; |
| 681 _globalState.managers[workerId] = worker; | 686 _globalState.managers[workerId] = worker; |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1426 JS('void', '#.clearInterval(#)', globalThis, _handle); | 1431 JS('void', '#.clearInterval(#)', globalThis, _handle); |
| 1427 } | 1432 } |
| 1428 _handle = null; | 1433 _handle = null; |
| 1429 } else { | 1434 } else { |
| 1430 throw new UnsupportedError("Canceling a timer."); | 1435 throw new UnsupportedError("Canceling a timer."); |
| 1431 } | 1436 } |
| 1432 } | 1437 } |
| 1433 } | 1438 } |
| 1434 | 1439 |
| 1435 bool hasTimer() => JS('', '#.setTimeout', globalThis) != null; | 1440 bool hasTimer() => JS('', '#.setTimeout', globalThis) != null; |
| OLD | NEW |