DOMWorkerThreads: Difference between revisions

no edit summary
No edit summary
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
== Web Worker API Proposal ==
== Web Worker API Proposal ==
== Abstract ==
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 ==


== API Proposal ==
== API Proposal ==
Line 28: Line 6:
<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 43: Line 20:
           attribute EventListener onunload;
           attribute EventListener onunload;
};
};


[NoInterfaceObject] interface WorkerGlobalScope
[NoInterfaceObject] interface WorkerGlobalScope
Line 60: 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 82: 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!"); ';
}


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


    var threads = []
function handler(e) {
    for (var i = 0; i < 10; i++) {
  sum += parseInt(e.data);
      var thread = wp.createWorker(scriptToRun);
  if (++c == 2) {
      thread.postMessage("hello");
    postMessage(sum);
      threads.push(thread);
  }
    }
}
</pre>
</code>
</blockquote>


  </script>
== References ==
  </body>
 
</html>
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.
 
== API Proposal For Shared Workers ==
 
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 127: 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