Skip to content

Commit 9fda90f

Browse files
jakearchibaldannevk
authored andcommitted
Make shared worker creation deterministic
To do this we introduced a new concept called parallel queue, which is also expected to be used by other specifications, such as Background Fetch. Fixes whatwg#1843.
1 parent e40797b commit 9fda90f

File tree

1 file changed

+139
-15
lines changed

1 file changed

+139
-15
lines changed

source

Lines changed: 139 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,23 +1876,136 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
18761876
rendered to the user. These terms are not meant to imply a visual medium; they must be considered
18771877
to apply to other media in equivalent ways.</p>
18781878

1879+
<!-- should find somewhere more appropriate to put this -->
1880+
<p>The term "transparent black" refers to the color with red, green, blue, and alpha channels all
1881+
set to zero.</p>
1882+
1883+
18791884
<div w-nodev>
18801885

1881-
<p>When an algorithm B says to return to another algorithm A, it implies that A called B. Upon
1882-
returning to A, the implementation must continue from where it left off in calling B. Some
1883-
algorithms run <dfn data-export="">in parallel</dfn>; this means that the algorithm's subsequent
1884-
steps are to be run, one after another, at the same time as other logic in the specification (e.g.
1885-
at the same time as the <span>event loop</span>). This specification does not define the precise
1886-
mechanism by which this is achieved, be it time-sharing cooperative multitasking, fibers, threads,
1887-
processes, using different hyperthreads, cores, CPUs, machines, etc. By contrast, an operation
1888-
that is to run <dfn>immediately</dfn> must interrupt the currently running task, run itself, and
1889-
then resume the previously running task.</p>
1886+
<h4>Parallelism</h4>
1887+
1888+
<p>To run steps <dfn data-export="">in parallel</dfn> means those steps are to be run, one after
1889+
another, at the same time as other logic in the standard (e.g., at the same time as the
1890+
<span>event loop</span>). This standard does not define the precise mechanism by which this is
1891+
achieved, be it time-sharing cooperative multitasking, fibers, threads, processes, using different
1892+
hyperthreads, cores, CPUs, machines, etc. By contrast, an operation that is to run
1893+
<dfn>immediately</dfn> must interrupt the currently running task, run itself, and then resume the
1894+
previously running task.</p>
1895+
1896+
<p>To avoid race conditions between different <span>in parallel</span> algorithms that operate on
1897+
the same data, a <span>parallel queue</span> can be used.</p>
1898+
1899+
<p>A <dfn data-export="">parallel queue</dfn> represents a queue of algorithm steps that must be
1900+
run in series.</p>
1901+
1902+
<p>A <span>parallel queue</span> has an <dfn>algorithm queue</dfn> (a <span>queue</span>),
1903+
initially empty.</p>
1904+
1905+
<p>To <dfn data-x="enqueue the following steps" data-lt="enqueue steps|enqueue the following
1906+
steps" data-export="" data-dfn-for="parallel queue">enqueue steps</dfn> to a <span>parallel
1907+
queue</span>, <span>enqueue</span> the algorithm steps to the <span>parallel queue</span>'s
1908+
<span>algorithm queue</span>.</p>
1909+
1910+
<p>To <dfn data-x="starting a new parallel queue" data-lt="start a new parallel queue|starting a
1911+
new parallel queue" data-export="">start a new parallel queue</dfn>, run the following steps:</p>
1912+
1913+
<ol>
1914+
<li><p>Let <var>parallelQueue</var> be a new <span>parallel queue</span>.</p></li>
1915+
1916+
<li>
1917+
<p>Run the following steps <span>in parallel</span>:</p>
1918+
1919+
<ol>
1920+
<li>
1921+
<p>While true:</p>
1922+
1923+
<ol>
1924+
<li><p>Let <var>steps</var> be the result of <span data-x="dequeue">dequeueing</span> from
1925+
<var>parallelQueue</var>'s <span>algorithm queue</span>.</p></li>
1926+
1927+
<li><p>If <var>steps</var> is not nothing, then run <var>steps</var>.</p></li>
1928+
1929+
<li><p>Assert: running <var>steps</var> did not throw an exception, as steps running <span>in
1930+
parallel</span> are not allowed to throw.</p></li>
1931+
</ol>
1932+
1933+
<p class="note">Implementations are not expected to implement this as a continuously running
1934+
loop. Algorithms in standards are to be easy to understand and are not necessarily great for
1935+
battery life or performance.</p>
1936+
</li>
1937+
</ol>
1938+
</li>
1939+
1940+
<li><p>Return <var>parallelQueue</var>.</p></li>
1941+
</ol>
1942+
1943+
<p class="note">Steps running <span>in parallel</span> can themselves run other steps in <span>in
1944+
parallel</span>. E.g., inside a <span>parallel queue</span> it can be useful to run a series of
1945+
steps in parallel with the queue.</p>
1946+
1947+
<div class="example">
1948+
<p>Imagine a standard defined <var>nameList</var> (a <span>list</span>), along with a method to
1949+
add a <var>name</var> to <var>nameList</var>, unless <var>nameList</var> already <span
1950+
data-x="list contains">contains</span> <var>name</var>, in which case it rejects.</p>
1951+
1952+
<p>The following solution suffers from race conditions:</p>
1953+
1954+
<ol>
1955+
<li><p>Let <var>p</var> be a new promise.</p></li>
18901956

1957+
<li>
1958+
<p>Run the following steps <span>in parallel</span>:</p>
1959+
1960+
<ol>
1961+
<li><p>If <var>nameList</var> <span data-x="list contains">contains</span> <var>name</var>,
1962+
reject <var>p</var> with a <code>TypeError</code> and abort these steps.</p></li>
1963+
1964+
<li><p>Do some potentially lengthy work.</p></li>
1965+
1966+
<li><p><span data-x="list append">Append</span> <var>name</var> to
1967+
<var>nameList</var>.</p></li>
1968+
1969+
<li><p>Resolve <var>p</var> with undefined.</p></li>
1970+
</ol>
1971+
</li>
1972+
1973+
<li><p>Return <var>p</var>.</p></li>
1974+
</ol>
1975+
1976+
<p>Two invocations of the above could run simultaneously, meaning <var>name</var> isn't in
1977+
<var>nameList</var> during step 2.1, but it <em>might be added</em> before step 2.3 runs,
1978+
meaning <var>name</var> ends up in <var>nameList</var> twice.</p>
1979+
1980+
<p>Parallel queues solve this. The standard would let <var>nameListQueue</var> be the result of
1981+
<span>starting a new parallel queue</span>, then:</p>
1982+
1983+
<ol>
1984+
<li><p>Let <var>p</var> be a new promise.</p></li>
1985+
1986+
<li>
1987+
<p><mark><span>Enqueue the following steps</span> to <var>nameListQueue</var>:</mark></p>
1988+
1989+
<ol>
1990+
<li><p>If <var>nameList</var> <span data-x="list contains">contains</span> <var>name</var>,
1991+
reject <var>p</var> with a <code>TypeError</code> and abort these steps.</p></li>
1992+
1993+
<li><p>Do some potentially lengthy work.</p></li>
1994+
1995+
<li><p><span data-x="list append">Append</span> <var>name</var> to
1996+
<var>nameList</var>.</p></li>
1997+
1998+
<li><p>Resolve <var>p</var> with undefined.</p></li>
1999+
</ol>
2000+
</li>
2001+
2002+
<li><p>Return <var>p</var>.</p></li>
2003+
</ol>
2004+
2005+
<p>The steps would now queue and the race is avoided.</p>
18912006
</div>
18922007

1893-
<!-- should find somewhere more appropriate to put this -->
1894-
<p>The term "transparent black" refers to the color with red, green, blue, and alpha channels all
1895-
set to zero.</p>
2008+
</div>
18962009

18972010

18982011
<h4>Resources</h4>
@@ -2404,6 +2517,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
24042517
<li>The <dfn data-x-href="https://infra.spec.whatwg.org/#stack">stack</dfn> data structure and the associated definitions for
24052518
<dfn data-x="stack push" data-x-href="https://infra.spec.whatwg.org/#stack-push">push</dfn> and
24062519
<dfn data-x="stack pop" data-x-href="https://infra.spec.whatwg.org/#stack-pop">pop</dfn></li>
2520+
<li>The <dfn data-x-href="https://infra.spec.whatwg.org/#queue">queue</dfn> data structure and the associated definitions for
2521+
<dfn data-x-href="https://infra.spec.whatwg.org/#queue-enqueue">enqueue</dfn> and
2522+
<dfn data-x-href="https://infra.spec.whatwg.org/#queue-dequeue">dequeue</dfn></li>
24072523
<li>The <dfn data-x="set" data-x-href="https://infra.spec.whatwg.org/#ordered-set">ordered set</dfn> data structure and the associated definition for
24082524
<dfn data-x="set append" data-x-href="https://infra.spec.whatwg.org/#set-append">append</dfn></li>
24092525
<li>The <dfn data-x-href="https://infra.spec.whatwg.org/#struct">struct</dfn> specification type and the associated definition for
@@ -97250,6 +97366,13 @@ interface <dfn>SharedWorker</dfn> : <span>EventTarget</span> {
9725097366
it was assigned by the object's constructor. It represents the <code>MessagePort</code> for
9725197367
communicating with the shared worker.</p>
9725297368

97369+
<p>A user agent has an associated <dfn>shared worker manager</dfn> which is the result of
97370+
<span>starting a new parallel queue</span>.</p>
97371+
97372+
<p class="note">Each user agent has a single <span>shared worker manager</span> for simplicity.
97373+
Implementations could use one per <span>origin</span>; that would not be observably different and
97374+
enables more concurrency.</p>
97375+
9725397376
<p>When the <dfn><code data-x="dom-SharedWorker">SharedWorker(<var>scriptURL</var>,
9725497377
<var>optons</var>)</code></dfn> constructor is invoked:</p>
9725597378

@@ -97293,7 +97416,7 @@ interface <dfn>SharedWorker</dfn> : <span>EventTarget</span> {
9729397416
object a secure context?</span> on <var>outside settings</var>.</p></li>
9729497417

9729597418
<li>
97296-
<p>Run these substeps <span>in parallel</span>:</p>
97419+
<p><span>Enqueue the following steps</span> to the <span>shared worker manager</span>:</p>
9729797420

9729897421
<ol>
9729997422
<li><p>Let <var>worker global scope</var> be null.</p></li>
@@ -97375,8 +97498,9 @@ interface <dfn>SharedWorker</dfn> : <span>EventTarget</span> {
9737597498
</ol>
9737697499
</li>
9737797500

97378-
<li><p>Otherwise, <span>run a worker</span> given <var>worker</var>, <var>urlRecord</var>,
97379-
<var>outside settings</var>, <var>outside port</var>, and <var>options</var>.</p></li>
97501+
<li><p>Otherwise, <span>in parallel</span>, <span>run a worker</span> given <var>worker</var>,
97502+
<var>urlRecord</var>, <var>outside settings</var>, <var>outside port</var>, and
97503+
<var>options</var>.</p></li>
9738097504
</ol>
9738197505
</li>
9738297506

0 commit comments

Comments
 (0)