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 |