Skip to content

Commit

Permalink
Fix #194: remove PortCollection in favor of advice
Browse files Browse the repository at this point in the history
The design of PortCollection was such that it exposed the details of
garbage collection. Since that is unacceptable to implementations it
has not been implemented and this commit removes the feature.
Unfortunately this means developers will have to do manual memory
management for ports. To address that this commit gives some advice on
how to do that.
  • Loading branch information
annevk committed Sep 29, 2015
1 parent f94f3c4 commit 5804d8c
Showing 1 changed file with 5 additions and 110 deletions.
115 changes: 5 additions & 110 deletions source
Expand Up @@ -94371,115 +94371,15 @@ interface <dfn>MessagePort</dfn> : <span>EventTarget</span> {

<h4>Broadcasting to many ports</h4>

<p class="critical">The API described in this section is controversial, as, in an attempt to solve
an architectural memory leak, it instead exposes the details of Garbage Collection. This is a
lose-lose scenario. A better solution is really needed here.</p>
<!-- NON-NORMATIVE SECTION -->

<p>Broadcasting to many ports is in principle relatively simple: keep an array of
<code>MessagePort</code> objects to send messages to, and iterate through the array to send a
message. However, this has one rather unfortunate effect: it prevents the ports from being garbage
collected, even if the other side has gone away.</p>

<p>To avoid this problem, the <code>PortCollection</code> object can be used. It acts as an opaque
array of <code>MessagePort</code> objects, thus allowing the objects to be garbage collected when
they stop being relevant, while still allowing scripts to iterate over the
<code>MessagePort</code> objects.</p>

<pre class="idl">[<span data-x="dom-PortCollection">Constructor</span>, Exposed=(Window,Worker)]
interface <dfn>PortCollection</dfn> {
void <span data-x="dom-PortCollection-add">add</span>(<span>MessagePort</span> port);
void <span data-x="dom-PortCollection-remove">remove</span>(<span>MessagePort</span> port);
void <span data-x="dom-PortCollection-clear">clear</span>();
void <span data-x="dom-PortCollection-iterate">iterate</span>(<span>PortCollectionCallback</span> callback);
};

callback <dfn>PortCollectionCallback</dfn> = void (<span>MessagePort</span> port);</pre>

<dl class="domintro">

<dt><var>portCollection</var> = new <code data-x="dom-PortCollection">PortCollection</code>()</dt>

<dd>

<p>Returns a new empty <code>PortCollection</code> object.</p>

</dd>

<dt><var>portCollection</var> . <code subdfn data-x="dom-PortCollection-add">add</code>(<var>port</var>)</dt>

<dd>

<p>Adds <var>port</var> to the collection, if it isn't already present.</p>

</dd>

<dt><var>portCollection</var> . <code subdfn data-x="dom-PortCollection-remove">remove</code>(<var>port</var>)</dt>

<dd>

<p>Removes <var>port</var> from the collection, if it is present.</p>

</dd>

<dt><var>portCollection</var> . <code subdfn data-x="dom-PortCollection-clear">clear</code>()</dt>

<dd>

<p>Removes all ports from the collection.</p>

</dd>

<dt><var>portCollection</var> . <code subdfn data-x="dom-PortCollection-iterate">iterate</code>(<var>callback</var>)</dt>

<dd>

<p>Calls <var>callback</var> for each port in the collection.</p>

</dd>

</dl>

<div w-nodev>

<p>A <code>PortCollection</code> object has an initially empty <dfn
data-x="concept-PortCollection-list">list of ports</dfn>. When a <code>MessagePort</code> object in
a <span data-x="concept-PortCollection-list">list of ports</span> is garbage collected, it must be
silently removed from that <span data-x="concept-PortCollection-list">list of ports</span>. Objects
in a <span data-x="concept-PortCollection-list">list of ports</span> are ordered chronologically by
the time at which they were most recently added; the least-recently added <code>MessagePort</code>
object is the first in the list, and the most-recently added <code>MessagePort</code> is the last
in the list.</p>

<p>The <dfn><code data-x="dom-PortCollection">PortCollection()</code></dfn> constructor must return
a new <code>PortCollection</code> object (with an empty <span
data-x="concept-PortCollection-list">list of ports</span>).</p>

<p>The <dfn><code data-x="dom-PortCollection-add">add()</code></dfn> method must add the
<code>MessagePort</code> given by the argument to the <code>PortCollection</code> object's <span
data-x="concept-PortCollection-list">list of ports</span>, unless the <code>MessagePort</code> is
already in the <span data-x="concept-PortCollection-list">list of ports</span>, in which case the
method does nothing. (Calling this method with a port already in the list does not move the port
to the end of the list.)</p>

<p>The <dfn><code data-x="dom-PortCollection-remove">remove()</code></dfn> method must remove the
<code>MessagePort</code> given by the argument from the <code>PortCollection</code> object's <span
data-x="concept-PortCollection-list">list of ports</span>, unless the <code>MessagePort</code> is
not in the <span data-x="concept-PortCollection-list">list of ports</span>, in which case the
method does nothing.</p>

<p>The <dfn><code data-x="dom-PortCollection-clear">clear()</code></dfn> method must remove all
<code>MessagePort</code> objects from the <code>PortCollection</code> object's <span
data-x="concept-PortCollection-list">list of ports</span>, returning it to the initial empty state.
If the <span data-x="concept-PortCollection-list">list of ports</span> is already empty, the method
does nothing.</p>

<p>The <dfn><code data-x="dom-PortCollection-iterate">iterate()</code></dfn> method must invoke its
<code>PortCollectionCallback</code> argument once for each <code>MessagePort</code> object in the
object's <span data-x="concept-PortCollection-list">list of ports</span>, in the order defined
above, with each invocation being passed the corresponding <code>MessagePort</code> object as the
callback's sole argument.</p>

</div>
collected, even if the other side has gone away. To avoid this problem, implement a simple
protocol whereby the other side acknowledges it still exists. If it doesn't do so after a certain
amount of time, assume it's gone, close the <code>MessagePort</code> object, and let it be garbage
collected.</p>


<h4 id="ports-and-garbage-collection">Ports and garbage collection</h4>
Expand Down Expand Up @@ -94511,11 +94411,6 @@ callback <dfn>PortCollectionCallback</dfn> = void (<span>MessagePort</span> port
<!-- ports in the ports attribute of a MessageEvent that isn't dispatched yet are safe because the
MessageEvent is safe -->

<p>There are no strong references from a <code>PortCollection</code> object to its
<code>MessagePort</code> objects. (That is in fact the whole point of <code>PortCollection</code>
objects: they allow for <code>MessagePort</code> objects to be referenced without preventing them
from being garbage collected.)</p>

</div>

<p class="note">Authors are strongly encouraged to explicitly close <code>MessagePort</code>
Expand Down

0 comments on commit 5804d8c

Please sign in to comment.