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

Side by Side Diff: frog/lib/isolate.dart

Issue 9358010: isolates in frog: playing with API improvements (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: '' Created 8 years, 10 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
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** 5 /**
6 * A native object that is shared across isolates. This object is visible to all 6 * A native object that is shared across isolates. This object is visible to all
7 * isolates running on the same worker (either UI or background web worker). 7 * isolates running on the same worker (either UI or background web worker).
8 * 8 *
9 * This is code that is intended to 'escape' the isolate boundaries in order to 9 * This is code that is intended to 'escape' the isolate boundaries in order to
10 * implement the semantics of friendly isolates in JavaScript. Without this we 10 * implement the semantics of friendly isolates in JavaScript. Without this we
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 155
156 _deserializeMessage(message) { 156 _deserializeMessage(message) {
157 if (_globalState.needSerialization) { 157 if (_globalState.needSerialization) {
158 return new Deserializer().deserialize(message); 158 return new Deserializer().deserialize(message);
159 } else { 159 } else {
160 // Nothing more to do. 160 // Nothing more to do.
161 return message; 161 return message;
162 } 162 }
163 } 163 }
164 164
165 /** Wait until all ports in a message are resolved. */
166 _waitForPendingPorts(var message, void callback()) {
167 final finder = new PendingSendPortFinder();
168 finder.traverse(message);
169 Futures.wait(finder.ports).then((_) => callback());
170 }
171
165 /** Default worker. */ 172 /** Default worker. */
166 class MainWorker { 173 class MainWorker {
167 int id = 0; 174 int id = 0;
168 void postMessage(msg) native "return \$globalThis.postMessage(msg);"; 175 void postMessage(msg) native "return \$globalThis.postMessage(msg);";
169 void set onmessage(f) native "\$globalThis.onmessage = f;"; 176 void set onmessage(f) native "\$globalThis.onmessage = f;";
170 void terminate() {} 177 void terminate() {}
171 } 178 }
172 179
173 /** 180 /**
174 * A web worker. This type is also defined in 'dart:dom', but we define it here 181 * A web worker. This type is also defined in 'dart:dom', but we define it here
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 Function fn; 326 Function fn;
320 String message; 327 String message;
321 328
322 IsolateEvent(this.isolate, this.fn, this.message); 329 IsolateEvent(this.isolate, this.fn, this.message);
323 330
324 void process() { 331 void process() {
325 isolate.eval(fn); 332 isolate.eval(fn);
326 } 333 }
327 } 334 }
328 335
329 /** Implementation of a send port on top of JavaScript. */ 336 /** Common functionality to all send ports. */
330 class SendPortImpl implements SendPort { 337 class BaseSendPort implements SendPort {
338 final int _isolateId;
331 339
332 const SendPortImpl(this._workerId, this._isolateId, this._receivePortId); 340 BaseSendPort(this._isolateId);
333
334 void send(var message, [SendPort replyTo = null]) {
335 if (replyTo !== null && !(replyTo is SendPortImpl)) {
336 throw "SendPort::send: Illegal replyTo type.";
337 }
338 IsolateNatives._sendMessage(_workerId, _isolateId, _receivePortId,
339 _serializeMessage(message), _serializeMessage(replyTo));
340 }
341
342 // TODO(sigmund): get rid of _sendNow (still used in corelib code)
343 void _sendNow(var message, replyTo) { send(message, replyTo); }
344 341
345 ReceivePortSingleShotImpl call(var message) { 342 ReceivePortSingleShotImpl call(var message) {
346 final result = new ReceivePortSingleShotImpl(); 343 final result = new ReceivePortSingleShotImpl();
347 this.send(message, result.toSendPort()); 344 this.send(message, result.toSendPort());
348 return result; 345 return result;
349 } 346 }
350 347
351 ReceivePortSingleShotImpl _callNow(var message) { 348 static void checkReplyTo(SendPort replyTo) {
352 final result = new ReceivePortSingleShotImpl(); 349 if (replyTo !== null
353 send(message, result.toSendPort()); 350 && replyTo is! NativeJsSendPort
354 return result; 351 && replyTo is! WorkerSendPort
352 && replyTo is! BufferingSendPort) {
353 throw new Exception("SendPort.send: Illegal replyTo port type");
354 }
355 } 355 }
356 356
357 bool operator==(var other) { 357 // TODO(sigmund): replace the current SendPort.call with the following:
358 return (other is SendPortImpl) && 358 //Future call(var message) {
359 //  final completer = new Completer();
360 //  final port = new ReceivePort.singleShot();
361 //  send(message, port.toSendPort());
362 //  port.receive((value, ignoreReplyTo) {
363 //    if (value is Exception) {
364 //  completer.completeException(value);
365 // } else {
366 // completer.complete(value);
367 // }
368 // });
369 //  return completer.future;
370 //}
371
372 abstract void send(var message, [SendPort replyTo]);
373 abstract bool operator ==(var other);
374 abstract int hashCode();
375 }
376
377 /** A send port that delivers messages in-memory via native JavaScript calls. */
378 class NativeJsSendPort extends BaseSendPort implements SendPort {
379 final ReceivePortImpl _receivePort;
380
381 const NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
382
383 void send(var message, [SendPort replyTo = null]) {
384 _waitForPendingPorts([message, replyTo], () {
385 checkReplyTo(replyTo);
386 // Check that the isolate still runs and the port is still open
387 final isolate = _globalState.isolates[_isolateId];
388 if (isolate == null) return;
389 if (_receivePort._callback == null) return;
390
391 // messages from WorkerSendPorts get forwarded by [_processWorkerMessage],
392 // in that case we no isolate is currently active, and the message was
393 // already serialized and deserialized.
394 final shouldSerialize = _globalState.currentContext == null;
395 _globalState.topEventLoop.enqueue(isolate, () {
396 if (_receivePort._callback != null) {
397 if (shouldSerialize) {
398 // Force serialization/deserialization as a simple way to ensure
399 // isolate communication restrictions are respected.
400 message = _deserializeMessage(_serializeMessage(message));
401 replyTo = _deserializeMessage(_serializeMessage(replyTo));
402 }
403 _receivePort._callback(message, replyTo);
404 }
405 }, 'receive ' + message);
406 });
407 }
408
409 bool operator ==(var other) => (other is NativeJsSendPort) &&
410 (_receivePort == other._receivePort);
411
412 int hashCode() => _receivePort._id;
413 }
414
415 /** A send port that delivers messages via worker.postMessage. */
416 class WorkerSendPort extends BaseSendPort implements SendPort {
417 final int _workerId;
418 final int _receivePortId;
419
420 const WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
421 : super(isolateId);
422
423 void send(var message, [SendPort replyTo = null]) {
424 _waitForPendingPorts([message, replyTo], () {
425 checkReplyTo(replyTo);
426 final workerMessage = _serializeMessage({
427 'command': 'message',
428 'port': _serializeMessage(this),
429 'msg': message,
430 'replyTo': _serializeMessage(replyTo)});
431
432 if (_globalState.isWorker) {
433 // communication from one worker to another go through the main worker:
434 _globalState.mainWorker.postMessage(workerMessage);
435 } else {
436 _globalState.workers[_workerId].postMessage(workerMessage);
437 }
438 });
439 }
440
441 bool operator ==(var other) {
442 return (other is WorkerSendPort) &&
359 (_workerId == other._workerId) && 443 (_workerId == other._workerId) &&
360 (_isolateId == other._isolateId) && 444 (_isolateId == other._isolateId) &&
361 (_receivePortId == other._receivePortId); 445 (_receivePortId == other._receivePortId);
362 } 446 }
363 447
364 int hashCode() { 448 int hashCode() {
365 return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId; 449 return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
366 } 450 }
451 }
367 452
368 final int _receivePortId; 453 /** A port that buffers messages until an underlying port gets resolve. */
369 final int _isolateId; 454 class BufferingSendPort extends BaseSendPort implements SendPort {
370 final int _workerId; 455 static int _bufferingCount = 0;
456
457 /** For implementing equals and hashcode. */
458 final int id;
459
460 /** Underlying port, when resolved. */
461 SendPort _port;
462
463 /**
464 * Future of the underlying port, so that we can detect when this port can be
465 * sent on messages.
466 */
467 Future<SendPort> _futurePort;
468
469 /** Pending messages (and reply ports). */
470 List pending;
471
472 BufferingSendPort(isolateId, this._futurePort)
473 : super(isolateId), id = _bufferingCount, pending = [] {
474 _bufferingCount++;
475 _futurePort.then((p) {
476 _port = p;
477 for (final message in pending) {
478 p.send(message[0], message[1]);
479 }
480 pending = null;
481 });
482 }
483
484 BufferingSendPort.fromPort(isolateId, this._port)
485 : super(isolateId), id = _bufferingCount {
486 _bufferingCount++;
487 }
488
489 void send(var message, [SendPort replyTo]) {
490 if (_port != null) {
491 _port.send(message, replyTo);
492 } else {
493 pending.add([message, replyTo]);
494 }
495 }
496
497 bool operator ==(var other) => (other is BufferingSendPort && id == other.id);
498 int hashCode() => id;
371 } 499 }
372 500
373 /** Default factory for receive ports. */ 501 /** Default factory for receive ports. */
374 class ReceivePortFactory { 502 class ReceivePortFactory {
375 503
376 factory ReceivePort() { 504 factory ReceivePort() {
377 return new ReceivePortImpl(); 505 return new ReceivePortImpl();
378 } 506 }
379 507
380 factory ReceivePort.singleShot() { 508 factory ReceivePort.singleShot() {
381 return new ReceivePortSingleShotImpl(); 509 return new ReceivePortSingleShotImpl();
382 } 510 }
383 } 511 }
384 512
385 /** Implementation of a multi-use [ReceivePort] on top of JavaScript. */ 513 /** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
386 class ReceivePortImpl implements ReceivePort { 514 class ReceivePortImpl implements ReceivePort {
515 int _id;
516 Function _callback;
517 static int _nextFreeId = 1;
518
387 ReceivePortImpl() 519 ReceivePortImpl()
388 : _id = _nextFreeId++ { 520 : _id = _nextFreeId++ {
389 _globalState.currentContext.register(_id, this); 521 _globalState.currentContext.register(_id, this);
390 } 522 }
391 523
392 void receive(void onMessage(var message, SendPort replyTo)) { 524 void receive(void onMessage(var message, SendPort replyTo)) {
393 _callback = onMessage; 525 _callback = onMessage;
394 } 526 }
395 527
396 void close() { 528 void close() {
397 _callback = null; 529 _callback = null;
398 _globalState.currentContext.unregister(_id); 530 _globalState.currentContext.unregister(_id);
399 } 531 }
400 532
401 /**
402 * Returns a fresh [SendPort]. The implementation is not allowed to cache
403 * existing ports.
404 */
405 SendPort toSendPort() { 533 SendPort toSendPort() {
406 return new SendPortImpl( 534 return new NativeJsSendPort(this, _globalState.currentContext.id);
407 _globalState.currentWorkerId, _globalState.currentContext.id, _id);
408 } 535 }
409
410 int _id;
411 Function _callback;
412
413 static int _nextFreeId = 1;
414 } 536 }
415 537
416 /** Implementation of a single-shot [ReceivePort]. */ 538 /** Implementation of a single-shot [ReceivePort]. */
417 class ReceivePortSingleShotImpl implements ReceivePort { 539 class ReceivePortSingleShotImpl implements ReceivePort {
418 540
419 ReceivePortSingleShotImpl() : _port = new ReceivePortImpl() { } 541 ReceivePortSingleShotImpl() : _port = new ReceivePortImpl() { }
420 542
421 void receive(void callback(var message, SendPort replyTo)) { 543 void receive(void callback(var message, SendPort replyTo)) {
422 _port.receive((var message, SendPort replyTo) { 544 _port.receive((var message, SendPort replyTo) {
423 _port.close(); 545 _port.close();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 579
458 return completer.future; 580 return completer.future;
459 } 581 }
460 582
461 static SendPort _startWorker(Isolate runnable, SendPort replyPort) { 583 static SendPort _startWorker(Isolate runnable, SendPort replyPort) {
462 var factoryName = _getJSConstructorName(runnable); 584 var factoryName = _getJSConstructorName(runnable);
463 if (_globalState.isWorker) { 585 if (_globalState.isWorker) {
464 _globalState.mainWorker.postMessage(_serializeMessage({ 586 _globalState.mainWorker.postMessage(_serializeMessage({
465 'command': 'spawn-worker', 587 'command': 'spawn-worker',
466 'factoryName': factoryName, 588 'factoryName': factoryName,
467 'replyPort': replyPort})); 589 'replyPort': _serializeMessage(replyPort)}));
468 } else { 590 } else {
469 _spawnWorker(factoryName, _serializeMessage(replyPort)); 591 _spawnWorker(factoryName, _serializeMessage(replyPort));
470 } 592 }
471 } 593 }
472 594
473
474 /** 595 /**
475 * The src url for the script tag that loaded this code. Used to create 596 * The src url for the script tag that loaded this code. Used to create
476 * JavaScript workers. 597 * JavaScript workers.
477 */ 598 */
478 static String get _thisScript() => 599 static String get _thisScript() =>
479 _thisScriptCache != null ? _thisScriptCache : _computeThisScript(); 600 _thisScriptCache != null ? _thisScriptCache : _computeThisScript();
480 601
481 static String _thisScriptCache; 602 static String _thisScriptCache;
482 603
483 // TODO(sigmund): fix - this code should be run synchronously when loading the 604 // TODO(sigmund): fix - this code should be run synchronously when loading the
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 */ 650 */
530 static _getEventData(e) native "return e.data"; 651 static _getEventData(e) native "return e.data";
531 652
532 /** 653 /**
533 * Process messages on a worker, either to control the worker instance or to 654 * Process messages on a worker, either to control the worker instance or to
534 * pass messages along to the isolate running in the worker. 655 * pass messages along to the isolate running in the worker.
535 */ 656 */
536 static void _processWorkerMessage(sender, e) { 657 static void _processWorkerMessage(sender, e) {
537 var msg = _deserializeMessage(_getEventData(e)); 658 var msg = _deserializeMessage(_getEventData(e));
538 switch (msg['command']) { 659 switch (msg['command']) {
660 // TODO(sigmund): delete after we migrate to Isolate2
539 case 'start': 661 case 'start':
540 _globalState.currentWorkerId = msg['id']; 662 _globalState.currentWorkerId = msg['id'];
541 var runnerObject = 663 var runnerObject =
542 _allocate(_getJSConstructorFromName(msg['factoryName'])); 664 _allocate(_getJSConstructorFromName(msg['factoryName']));
543 var serializedReplyTo = msg['replyTo']; 665 var serializedReplyTo = msg['replyTo'];
544 _globalState.topEventLoop.enqueue(new IsolateContext(), function() { 666 _globalState.topEventLoop.enqueue(new IsolateContext(), function() {
545 var replyTo = _deserializeMessage(serializedReplyTo); 667 var replyTo = _deserializeMessage(serializedReplyTo);
546 IsolateNatives._startIsolate(runnerObject, replyTo); 668 _startIsolate(runnerObject, replyTo);
547 }, 'worker-start'); 669 }, 'worker-start');
548 _globalState.topEventLoop.run(); 670 _globalState.topEventLoop.run();
549 break; 671 break;
672 case 'start2':
673 _globalState.currentWorkerId = msg['id'];
674 Function entryPoint = _getJSFunctionFromName(msg['functionName']);
675 var replyTo = _deserializeMessage(msg['replyTo']);
676 _globalState.topEventLoop.enqueue(new IsolateContext(), function() {
677 _startIsolate2(entryPoint, replyTo);
678 }, 'worker-start');
679 _globalState.topEventLoop.run();
680 break;
681 // TODO(sigmund): delete after we migrate to Isolate2
550 case 'spawn-worker': 682 case 'spawn-worker':
551 _spawnWorker(msg['factoryName'], msg['replyPort']); 683 _spawnWorker(msg['factoryName'], msg['replyPort']);
552 break; 684 break;
685 case 'spawn-worker2':
686 _spawnWorker2(msg['functionName'], msg['uri'], msg['replyPort']);
687 break;
553 case 'message': 688 case 'message':
554 _sendMessage(msg['workerId'], msg['isolateId'], msg['portId'], 689 final iid = _globalState.currentContext == null ? '?' : '${_globalState. currentContext.id }';
555 msg['msg'], msg['replyTo']); 690 final port = _deserializeMessage(msg['port']);
691 port.send(msg['msg'], _deserializeMessage(msg['replyTo']));
556 _globalState.topEventLoop.run(); 692 _globalState.topEventLoop.run();
557 break; 693 break;
558 case 'close': 694 case 'close':
559 _log("Closing Worker"); 695 _log("Closing Worker");
560 _globalState.workers.remove(sender.id); 696 _globalState.workers.remove(sender.id);
561 sender.terminate(); 697 sender.terminate();
562 _globalState.topEventLoop.run(); 698 _globalState.topEventLoop.run();
563 break; 699 break;
564 case 'log': 700 case 'log':
565 _log(msg['msg']); 701 _log(msg['msg']);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 // TODO(sigmund): find a browser-generic way to support this. 742 // TODO(sigmund): find a browser-generic way to support this.
607 static var _getJSConstructorName(Isolate runnable) native """ 743 static var _getJSConstructorName(Isolate runnable) native """
608 return runnable.constructor.name; 744 return runnable.constructor.name;
609 """; 745 """;
610 746
611 /** Find a constructor given it's name. */ 747 /** Find a constructor given it's name. */
612 static var _getJSConstructorFromName(String factoryName) native """ 748 static var _getJSConstructorFromName(String factoryName) native """
613 return \$globalThis[factoryName]; 749 return \$globalThis[factoryName];
614 """; 750 """;
615 751
752 static var _getJSFunctionFromName(String functionName) native """
753 return \$globalThis[functionName];
754 """;
755
756 static String _getJSFunctionName(Function f) native "return f.name || null;";
757
616 /** Create a new JavasSript object instance given it's constructor. */ 758 /** Create a new JavasSript object instance given it's constructor. */
617 static var _allocate(var ctor) native "return new ctor();"; 759 static var _allocate(var ctor) native "return new ctor();";
618 760
619 /** Starts a non-worker isolate. */ 761 /** Starts a non-worker isolate. */
620 static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) { 762 static SendPort _startNonWorker(Isolate runnable, SendPort replyTo) {
621 // Spawn a new isolate and create the receive port in it. 763 // Spawn a new isolate and create the receive port in it.
622 final spawned = new IsolateContext(); 764 final spawned = new IsolateContext();
623 765
624 // Instead of just running the provided runnable, we create a 766 // Instead of just running the provided runnable, we create a
625 // new cloned instance of it with a fresh state in the spawned 767 // new cloned instance of it with a fresh state in the spawned
626 // isolate. This way, we do not get cross-isolate references 768 // isolate. This way, we do not get cross-isolate references
627 // through the runnable. 769 // through the runnable.
628 final ctor = _getJSConstructor(runnable); 770 final ctor = _getJSConstructor(runnable);
629 _globalState.topEventLoop.enqueue(spawned, function() { 771 _globalState.topEventLoop.enqueue(spawned, function() {
630 _startIsolate(_allocate(ctor), replyTo); 772 _startIsolate(_allocate(ctor), replyTo);
631 }, 'nonworker start'); 773 }, 'nonworker start');
632 } 774 }
633 775
634 /** Given a ready-to-start runnable, start running it. */ 776 /** Given a ready-to-start runnable, start running it. */
635 static void _startIsolate(Isolate isolate, SendPort replyTo) { 777 static void _startIsolate(Isolate isolate, SendPort replyTo) {
636 _fillStatics(_globalState.currentContext); 778 _fillStatics(_globalState.currentContext);
637 ReceivePort port = new ReceivePort(); 779 ReceivePort port = new ReceivePort();
638 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort()); 780 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
639 isolate._run(port); 781 isolate._run(port);
640 } 782 }
641 783
642 static void _sendMessage(int workerId, int isolateId, int receivePortId, 784 // TODO(sigmund): clean up above, after we make the new API the default:
643 message, replyTo) { 785
644 // Both the message and the replyTo are already serialized. 786 static _spawn2(String functionName, String uri, bool isLight) {
645 if (workerId == _globalState.currentWorkerId) { 787 Completer<SendPort> completer = new Completer<SendPort>();
646 var isolate = _globalState.isolates[isolateId]; 788 ReceivePort port = new ReceivePort.singleShot();
647 if (isolate == null) return; // Isolate has been closed. 789 port.receive((msg, SendPort replyPort) {
648 var receivePort = isolate.lookup(receivePortId); 790 assert(msg == _SPAWNED_SIGNAL);
649 if (receivePort == null) return; // ReceivePort has been closed. 791 completer.complete(replyPort);
650 _globalState.topEventLoop.enqueue(isolate, () { 792 });
651 if (receivePort._callback != null) { 793
652 receivePort._callback( 794 SendPort signalReply = port.toSendPort();
653 _deserializeMessage(message), _deserializeMessage(replyTo)); 795
654 } 796 if (_globalState.useWorkers && !isLight) {
655 }, 'receive ' + message); 797 _startWorker2(functionName, uri, signalReply);
656 } else { 798 } else {
657 var worker; 799 _startNonWorker2(functionName, uri, signalReply);
658 // communication between workers go through the main worker 800 }
659 if (_globalState.isWorker) { 801 return new BufferingSendPort(
660 worker = _globalState.mainWorker; 802 _globalState.currentContext.id, completer.future);
661 } else { 803 }
662 // TODO(sigmund): make sure this works 804
663 worker = _globalState.workers[workerId]; 805 static SendPort _startWorker2(
664 } 806 String functionName, String uri, SendPort replyPort) {
665 worker.postMessage(_serializeMessage({ 807 if (_globalState.isWorker) {
666 'command': 'message', 808 _globalState.mainWorker.postMessage(_serializeMessage({
667 'workerId': workerId, 809 'command': 'spawn-worker2',
668 'isolateId': isolateId, 810 'functionName': functionName,
669 'portId': receivePortId, 811 'uri': uri,
670 'msg': message, 812 'replyPort': replyPort}));
671 'replyTo': replyTo })); 813 } else {
814 _spawnWorker2(functionName, uri, replyPort);
672 } 815 }
673 } 816 }
817
818 static SendPort _startNonWorker2(
819 String functionName, String uri, SendPort replyPort) {
820 _globalState.topEventLoop.enqueue(new IsolateContext(), function() {
821 final func = _getJSFunctionFromName(functionName);
822 _startIsolate2(func, replyPort);
823 }, 'nonworker start');
824 }
825
826 static void _startIsolate2(Function topLevel, SendPort replyTo) {
827 _fillStatics(_globalState.currentContext);
828 final port = new ReceivePort();
829 replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
830 topLevel(port);
831 }
832
833 /**
834 * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
835 * name for the isolate entry point class.
836 */
837 static void _spawnWorker2(functionName, uri, replyPort) {
838 if (uri == null) uri = _thisScript;
839 final worker = _newWorker(uri);
840 worker.onmessage = (e) { _processWorkerMessage(worker, e); };
841 var workerId = _globalState.nextWorkerId++;
842 // We also store the id on the worker itself so that we can unregister it.
843 worker.id = workerId;
844 _globalState.workers[workerId] = worker;
845 worker.postMessage(_serializeMessage({
846 'command': 'start2',
847 'id': workerId,
848 // Note: we serialize replyPort twice because the child worker needs to
849 // first deserialize the worker id, before it can correctly deserialize
850 // the port (port deserialization is sensitive to what is the current
851 // workerId).
852 'replyTo': _serializeMessage(replyPort),
853 'functionName': functionName }));
854 }
674 } 855 }
856
857 class Isolate2Impl implements Isolate2 {
858 SendPort sendPort;
859
860 Isolate2Impl(this.sendPort);
861
862 void stop() {}
863 }
864
865 class IsolateFactory implements Isolate2 {
866
867 factory Isolate2.fromCode(Function topLevelFunction) {
868 final name = IsolateNatives._getJSFunctionName(topLevelFunction);
869 if (name == null) {
870 throw new UnsupportedOperationException(
871 "only top-level functions can be spawned.");
872 }
873 return new Isolate2Impl(IsolateNatives._spawn2(name, null, false));
874 }
875
876 factory Isolate2.fromUri(String uri) {
877 return new Isolate2Impl(IsolateNatives._spawn2(null, uri, false));
878 }
879 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698