DOMWorkerThreads: Difference between revisions

no edit summary
No edit summary
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Web Worker API Proposal ==
== Web Worker API Proposal ==


== Abstract ==
== API Proposal ==
 
This is an API '''proposal''' for DOM Worker Threads.
 
At this time this document is not complete.  While we invite discussion on this topic, this is not a stable API proposal, and Mozilla won't implement anything based on it till it becomes stable.
 
Look for a post to mozilla.dev.platform when this proposal is ready to be discussed.
 
== Introduction ==
 
=== Use Cases ===
 
=== Terminology ===
 
A '''worker''' is an execution context for JavaScript that runs off of the main UI thread. The global scope for a worker is almost empty - familiar objects such as <code>window</code> and <code>document</code> are not available, nor is the Mozilla-specific <code>Components</code> object.
 
A '''worker pool''' is a collection of related workers. Workers within a pool can communicate with each other freely, but workers cannot communicate with workers from another pool.
 
== Conformance ==
 
== Dependencies ==
 
== Specification Proposal ==


<blockquote>
<blockquote>
<code>
<code>
<pre>
<pre>
#include "nsISupports.idl"


interface nsIDOMWorkerThread;
[NoInterfaceObject] interface WorkerFactory {
interface nsIScriptError;
  Worker createWorker(in DOMString scriptURL);
};


interface Worker
interface Worker {
{
   void postMessage(in DOMString aMessage);
   void postMessage(in DOMString aMessage);


Line 61: Line 38:
   void showNotification(in DOMString title, in DOMString subtitle, in DOMString description);
   void showNotification(in DOMString title, in DOMString subtitle, in DOMString description);
   void showNotification(in DOMString title, in DOMString subtitle, in DOMString description, in VoidCallback onclick);
   void showNotification(in DOMString title, in DOMString subtitle, in DOMString description, in VoidCallback onclick);
};
[NoInterfaceObject] interface WorkerFactory {
  Worker createWorker(in DOMString scriptURL);
  Worker createSharedWorker(in DOMString name, in DOMString scriptURL);
};
};


Line 83: Line 55:
</blockquote>
</blockquote>


=== The worker's scope ===
=== Sample usage ===


The worker's scope is far more limited. See <code>WorkerGlobalScope</code> above for details.
This is a '''very''' suboptimal way of calculating a number in the Fibonacci sequence.


=== Sample usage ===
Main page:
<blockquote>
<code>
<pre>
worker = createWorker("f.js");
worker.onmessage = function(e) {
  alert("The 100th Fibonacci number is " + e.data);
}
worker.postMessage(100);
</pre>
</code>
</blockquote>


f.js:
<blockquote>
<blockquote>
<code>
<code>
<pre>
<pre>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
parent.onmessage = function(e) {
<html>
  if (e.data <= 1)
   <title>Test threads</title>
    postMessage(e.data);
   <body>
 
   <script language="javascript">
  w1 = createWorker("f.js");
    var scriptToRun = 'function messageListener(message, source) { ' +
  w1.onmessage = handler;
                      '  dump("Worker: " + message + "\\n"); ' +
   w1.postMessage(e.data - 1);
                      '} ' +
    
                      'for (var i = 0; i < 10000000; i++) { ' +
   w2 = createWorker("f.js");
                      ' /* do something */ ' +
  w2.onmessage = handler;
                      '} '+
  w2.postMessage(e.data - 2);
                      'postMessageToPool("Done!"); ';
}
 
c = 0;
sum = 0;
 
function handler(e) {
  sum += parseInt(e.data);
  if (++c == 2) {
    postMessage(sum);
  }
}
</pre>
</code>
</blockquote>


    var wp = navigator.newWorkerPool();
== References ==
    wp.messageListener = function(message, source) {
      dump("Pool: " + message + "\n");
    };
    wp.errorListener = function(error, source) {
      dump("Pool: error = '" + error + "'\n");
    }


    var threads = []
The only thing I've seen so far is the [http://code.google.com/apis/gears/api_workerpool.html Google Gears WorkerPool API]. We would certainly like to provide a API that would make migrating Gears code trivial.
    for (var i = 0; i < 10; i++) {
      var thread = wp.createWorker(scriptToRun);
      thread.postMessage("hello");
      threads.push(thread);
    }


  </script>
== API Proposal For Shared Workers ==
  </body>
 
</html>
If we want to support shared workers in the initial release of this spec, here are two proposals that will work with the above initial API.
 
=== Proposal 1 ===
 
<blockquote>
<code>
<pre>
 
[NoInterfaceObject] interface WorkerFactory {
  ...
  Worker createSharedWorker(in DOMString name, in DOMString scriptURL);
};
 
[NoInterfaceObject] interface WorkerParent {
  void postMessage(in DOMString aMessage);
  attribute EventListener onmessage;
};


</pre>
</pre>
Line 128: Line 130:
</blockquote>
</blockquote>


== Not In This Specification ==
<code>createSharedWorker</code> creates a new <code>Worker</code> object that interacts with the same <code>WorkerGlobalScope</code> as any previously existing <code>Worker</code>s.
 
When a shared <code>Worker</code> receives a message it can send data back to the sender using the <code>Event.source</code> property which is a <code>WorkerParent</code>.


== References ==
Using <code>WorkerGlobalScope.postMessage</code> and <code>WorkerGlobalScope.onmessage</code> results in a message being sent to the first context that opened the shared worker (or nothing if that context is dead).
 
Downsides with this proposal:
* There is no way to communicate back unless first communicated to.
* The first one to instantiate a shared worker get special treatment.
 
=== Proposal 2 ===
 
<blockquote>
<code>
<pre>
 
[NoInterfaceObject] interface WorkerFactory {
  ...
  MessagePort connectToSharedWorker(in DOMString name, in DOMString scriptURL);
};
 
[NoInterfaceObject] interface WorkerGlobalScope {
  ...
          attribute EventListener onconnect; 
};
 
</pre>
</code>
</blockquote>
 
<code>connectToSharedWorker</code> creates a two new <code>MessagePort</code> which are entangled with each other. One of the two ports is returned, and the other is sent to the <code>Worker</code> with the given name. If such a <code>Worker</code> does not yet exist, one is created.


The only thing I've seen so far is the [http://code.google.com/apis/gears/api_workerpool.html Google Gears WorkerPool API]. We would certainly like to provide a compatibility API that would make migrating Gears code trivial.
The <code>Worker</code> receives the other <code>MessagePort</code> through an <code>onconnect</code> <code>Event</code> fired on the <code>WorkerGlobalScope</code> object.


== Acknowledgements ==
* There is no way to get a reference to the shared <code>Worker</code> object itself.
* Communication for shared workers is different from communication for non-shared ones.
Confirmed users
716

edits