Skip to content

Commit fb902ec

Browse files
committed
Apply P0155R0.
1 parent 487c83c commit fb902ec

File tree

7 files changed

+894
-64
lines changed

7 files changed

+894
-64
lines changed

README.md

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,21 @@
1-
Document Number: N4506
2-
Date: 2015-05-05
1+
Document Number: N4579
2+
Date: 2015-02-22
33
Revises:
44
Project: Programming Language C++
55
Project Number: TS 19570
66
Reply-to: Jared Hoberock
77
NVIDIA Corporation
88
99

10-
# Parallelism TS Editor's Report, post-Lenexa mailing
10+
# Parallelism TS Editor's Report, pre-Jacksonville mailing
1111

12-
N4505 is the latest Parallelism TS Working Draft. It contains editorial and technical changes to the Parallelism TS to apply the following revisions:
12+
N4578 is the proposed working draft of Parallelism TS Version 2. It contains technical changes to the Parallelism TS to apply the following revision:
1313

14-
* N4274 - Relaxing Packing Rules for Exceptions Thrown by Parallel Algorithms - Proposed Wording (Revision 1)
15-
* Feature test macro for the Parallelism TS
14+
* P0155R0 - Task Block R5
1615

17-
N4505 updates the previous draft, N4407, published in the pre-Lenexa mailing.
18-
19-
N4507 is document N4505 reformatted as a TS document. It updates N4409, which was published in the pre-Lenexa mailing.
16+
N4578 updates the previous draft, N4505, published in the post-Lenexa mailing.
2017

2118
## Technical Changes
2219

23-
* Applied N4274, which relaxes the exception packaging rules for exceptions thrown by parallel algorithms. Additionally, changed instances of "terminates with (exception)" phrasing to "exits via (exception)", as directed by the Library Working Group.
24-
25-
* Introduced the feature test macro `__cpp_lib_experimental_parallel_algorithm` for the functionality of the Parallelism TS as directed by SG1.
26-
27-
## Editorial Changes
28-
29-
* Promoted subsection 1.3.1, which was incorrectly grouped under section 1.3, to section 1.4.
20+
* Applied P0155R0, which introduces support for fork-join task parallelism via task blocks.
3021

front_matter.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<cxx-titlepage stage="draft">
2-
<cxx-docnum>DXXXX</cxx-docnum>
2+
<cxx-docnum>N4578</cxx-docnum>
33
<cxx-project-number>19570</cxx-project-number>
4-
<time pubdate="">2016-02-18</time>
4+
<time pubdate="">2016-02-22</time>
55
<cxx-revises><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4505.html">N4505</a></cxx-revises>
66
<cxx-editor>
77
Jared Hoberock<br/>
88
NVIDIA Corporation<br/>
99
<cxx-email>[email protected]</cxx-email>
1010
</cxx-editor>
11-
<h1>Working Draft, Technical Specification for C++ Extensions for Parallelism Version 2</h1>
11+
<h1>Technical Specification for C++ Extensions for Parallelism Version 2</h1>
1212
</cxx-titlepage>
1313

1414
<cxx-toc></cxx-toc>

general.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ <h1>Feature-testing recommendations</h1>
149149
<code>&lt;experimental/numeric&gt;</code>
150150
</td>
151151
</tr>
152+
<tr>
153+
<td><code>__cpp_lib_experimental_parallel_task_block</code></td>
154+
<td>201510</td>
155+
<td>
156+
<code>&lt;experimental/task_block&gt;</code><br>
157+
</td>
158+
</tr>
152159
</thead>
153160
</table>
154161
</cxx-section>

main.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<cxx-include href="execution_policies.html"></cxx-include>
1313
<cxx-include href="exceptions.html"></cxx-include>
1414
<cxx-include href="algorithms.html"></cxx-include>
15+
<cxx-include href="task_block.html"></cxx-include>
1516
<cxx-publish-button source="https://github.com/cplusplus/parallelism-ts"></cxx-publish-button>
1617

1718
</body>

parallelism-ts.html

Lines changed: 576 additions & 45 deletions
Large diffs are not rendered by default.

parallelism-ts.pdf

-207 KB
Binary file not shown.

task_block.html

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
<ins>
2+
<cxx-clause id="parallel.task_block">
3+
<h1>Task Block</h1>
4+
5+
<cxx-section id="parallel.task_block.synopsis">
6+
<h1>Header <code>&lt;experimental/task_block&gt;</code> synopsis</h1>
7+
8+
<pre>
9+
namespace std {
10+
namespace experimental {
11+
namespace parallel {
12+
inline namespace v2 {
13+
class task_cancelled_exception;
14+
15+
class task_block;
16+
17+
template&lt;class F&gt;
18+
void define_task_block(F&& f);
19+
20+
template&lt;class f&gt;
21+
void define_task_block_restore_thread(F&& f);
22+
}
23+
}
24+
}
25+
}
26+
</pre>
27+
</cxx-section>
28+
29+
<cxx-section id="parallel.task_block.task_cancelled_exception">
30+
<h1>Class <code>task_cancelled_exception</code></h1>
31+
<pre>
32+
33+
namespace std {
34+
namespace experimental {
35+
namespace parallel
36+
inline namespace v2 {
37+
38+
class task_cancelled_exception : public exception
39+
{
40+
public:
41+
task_cancelled_exception() noexcept;
42+
virtual const char* what() const noexcept;
43+
};
44+
}
45+
}
46+
}
47+
}
48+
</pre>
49+
50+
<p>
51+
The class <code>task_cancelled_exception</code> defines the type of objects thrown by
52+
<code>task_block::run</code> or <code>task_block::wait</code> if they detect than an
53+
exception is pending within the current parallel block. See <cxx-ref to="parallel.task_block.exceptions"></cxx-ref>, below.
54+
</p>
55+
56+
<cxx-section id="parallel.task_block.task_cancelled_exception.what">
57+
<h1><code>task_cancelled_exception</code> member function <code>what</code></h1>
58+
59+
<cxx-function>
60+
<cxx-signature>virtual const char* what() const noexcept</cxx-signature>
61+
62+
<cxx-returns>
63+
An implementation-defined NTBS.
64+
</cxx-returns>
65+
</cxx-function>
66+
</cxx-section>
67+
</cxx-section>
68+
69+
<cxx-section id="parallel.task_block.class">
70+
<h1>Class <code>task_block</code></h1>
71+
<pre>
72+
73+
namespace std {
74+
namespace experimental {
75+
namespace parallel {
76+
inline namespace v2 {
77+
78+
class task_block
79+
{
80+
private:
81+
~task_block();
82+
83+
public:
84+
task_block(const task_block&) = delete;
85+
task_block& operator=(const task_block&) = delete;
86+
void operator&() const = delete;
87+
88+
template&lt;class F&gt;
89+
void run(F&& f);
90+
91+
void wait();
92+
};
93+
}
94+
}
95+
}
96+
}
97+
</pre>
98+
99+
<p>
100+
The class <code>task_block</code> defines an interface for forking and joining parallel tasks. The <code>define_task_block</code> and <code>define_task_block_restore_thread</code> function templates create an object of type <code>task_block</code> and pass a reference to that object to a user-provided function object.
101+
</p>
102+
103+
<p>
104+
An object of class <code>task_block</code> cannot be constructed, destroyed, copied, or moved except by the implementation of the task block library. Taking the address of a <code>task_block</code> object via <code>operator&</code> is ill-formed. Obtaining its address by any other means (including <code>addressof</code>) results in a pointer with an unspecified value; dereferencing such a pointer results in undefined behavior.
105+
</p>
106+
107+
<p>
108+
A <code>task_block</code> is <em>active</em> if it was created by the nearest enclosing task block, where “task block” refers to an
109+
invocation of <code>define_task_block</code> or <code>define_task_block_restore_thread</code> and “nearest enclosing” means the most
110+
recent invocation that has not yet completed. Code designated for execution in another thread by means other
111+
than the facilities in this section (e.g., using <code>thread</code> or <code>async</code>) are not enclosed in the task block and a
112+
<code>task_block</code> passed to (or captured by) such code is not active within that code. Performing any operation on a
113+
<code>task_block</code> that is not active results in undefined behavior.
114+
</p>
115+
116+
<p>
117+
When the argument to <code>task_block::run</code> is called, no <code>task_block</code> is active, not even the <code>task_block</code> on which <code>run</code> was called.
118+
(The function object should not, therefore, capture a <code>task_block</code> from the surrounding block.)
119+
</p>
120+
121+
<cxx-example>
122+
<pre>define_task_block([&](auto& tb) {
123+
tb.run([&]{
124+
tb.run([] { f(); }); // Error: tb is not active within run
125+
define_task_block([&](auto& tb2) { // Define new task block
126+
tb2.run(f);
127+
...
128+
});
129+
});
130+
...
131+
});
132+
</pre>
133+
</cxx-example><pre>
134+
</pre>
135+
136+
<cxx-note>
137+
Implementations are encouraged to diagnose the above error at translation time.
138+
</cxx-note>
139+
140+
<cxx-section id="parallel.task_block.class.run">
141+
142+
<h1><code>task_block</code> member function template <code>run</code></h1>
143+
144+
<cxx-function>
145+
<cxx-signature>template&lt;class F&gt; void run(F&& f);</cxx-signature>
146+
147+
<cxx-requires>
148+
<code>F</code> shall be <code>MoveConstructible</code>. <code><em>DECAY_COPY</em>(std::forward&lt;F&gt;(f))()</code> shall be a valid expression.
149+
</cxx-requires>
150+
151+
<cxx-preconditions>
152+
<code>*this</code> shall be the active <code>task_block</code>.
153+
</cxx-preconditions>
154+
155+
<cxx-effects>
156+
Evaluates <code><em>DECAY_COPY</em>(std::forward&lt;F&gt;(f))()</code>, where <code><em>DECAY_COPY</em>(std::forward&lt;F&gt;(f))</code>
157+
is evaluated synchronously within the current thread. The call to the resulting copy of the function object is
158+
permitted to run on an unspecified thread created by the implementation in an unordered fashion relative to
159+
the sequence of operations following the call to <code>run(f)</code> (the continuation), or indeterminately sequenced
160+
within the same thread as the continuation. The call to <code>run</code> synchronizes with the call to the function
161+
object. The completion of the call to the function object synchronizes with the next invocation of <code>wait</code> on
162+
the same <code>task_block</code> or completion of the nearest enclosing task block (i.e., the <code>define_task_block</code> or
163+
<code>define_task_block_restore_thread</code> that created this <code>task_block</code>).
164+
</cxx-effects>
165+
166+
<cxx-throws>
167+
<code>task_cancelled_exception</code>, as described in <cxx-ref to="parallel.task_block.exceptions"></cxx-ref>.
168+
</cxx-throws>
169+
170+
<cxx-remarks>
171+
The <code>run</code> function may return on a thread other than the one on which it was called; in such cases,
172+
completion of the call to <code>run</code> synchronizes with the continuation.
173+
174+
<cxx-note> The return from <code>run</code> is ordered similarly to an ordinary function call in a single thread.</cxx-note>
175+
</cxx-remarks>
176+
177+
<cxx-remarks>
178+
The invocation of the user-supplied function object <code>f</code> may be immediate or may be delayed until
179+
compute resources are available. <code>run</code> might or might not return before the invocation of <code>f</code> completes.
180+
</cxx-remarks>
181+
182+
</cxx-function>
183+
</cxx-section>
184+
185+
<cxx-section id="parallel.task_block.class.wait">
186+
187+
<h1><code>task_block</code> member function <code>wait</code></h1>
188+
189+
<cxx-function>
190+
<cxx-signature>void wait();</cxx-signature>
191+
192+
<cxx-preconditions><code>*this</code> shall be the active <code>task_block</code>.</cxx-preconditions>
193+
194+
<cxx-effects>
195+
Blocks until the tasks spawned using this <code>task_block</code> have completed.
196+
</cxx-effects>
197+
198+
<cxx-throws>
199+
<code>task_cancelled_exception</code>, as described in <cxx-ref to="parallel.task_block.exceptions"></cxx-ref>.
200+
</cxx-throws>
201+
202+
<cxx-postconditions>
203+
All tasks spawned by the nearest enclosing task block have completed.
204+
</cxx-postconditions>
205+
206+
<cxx-remarks>
207+
The <code>wait</code> function may return on a thread other than the one on which it was called; in such cases, completion of the call to <code>wait</code> synchronizes with subsequent operations.
208+
209+
<cxx-note>The return from wait is ordered similarly to an ordinary function call in a single thread.</cxx-note>
210+
211+
<cxx-example><pre>
212+
define_task_block([&](auto& tb) {
213+
tb.run([&]{ process(a, w, x); }); // Process a[w] through a[x]
214+
if (y &lt; x) tb.wait(); // Wait if overlap between [w,x) and [y,z)
215+
process(a, y, z); // Process a[y] through a[z]
216+
});
217+
</pre>
218+
</cxx-example>
219+
</cxx-remarks>
220+
</cxx-function>
221+
</cxx-section>
222+
</cxx-section>
223+
224+
<cxx-section id="parallel.task_block.define_task_block">
225+
<h1>Function template <code>define_task_block</code></h1>
226+
227+
<cxx-function>
228+
<cxx-signature>template&lt;class F&gt;
229+
void define_task_block(F&& f);
230+
</cxx-signature>
231+
232+
<cxx-signature>template&lt;class F&gt;
233+
void define_task_block_restore_thread(F&& f);
234+
</cxx-signature>
235+
236+
<cxx-requires>
237+
Given an lvalue <code>tb</code> of type <code>task_block</code>, the expression <code>f(tb)</code> shall be well-formed
238+
</cxx-requires>
239+
240+
<cxx-effects>
241+
Constructs a <code>task_block</code> <code>tb</code> and calls <code>f(tb)</code>.
242+
</cxx-effects>
243+
244+
<cxx-throws>
245+
<code>exception_list</code>, as specified in <cxx-ref to="parallel.task_block.exceptions"></cxx-ref>.
246+
</cxx-throws>
247+
248+
<cxx-postconditions>
249+
All tasks spawned from <code>f</code> have finished execution.
250+
</cxx-postconditions>
251+
252+
<cxx-remarks>
253+
The <code>define_task_block</code> function may return on a thread other than the one on which it was called
254+
unless there are no task blocks active on entry to <code>define_task_block</code> (see <cxx-ref to="parallel.task_block.class"></cxx-ref>), in which
255+
case the function returns on the original thread. When <code>define_task_block</code> returns on a different thread,
256+
it synchronizes with operations following the call. <cxx-note> The return from define_task_block is ordered
257+
similarly to an ordinary function call in a single thread.</cxx-note> The <code>define_task_block_restore_thread</code>
258+
function always returns on the same thread as the one on which it was called.
259+
</cxx-remarks>
260+
261+
<cxx-notes>
262+
It is expected (but not mandated) that <code>f</code> will (directly or indirectly) call <code>tb.run(<em>function-object</em>)</code>.
263+
</cxx-notes>
264+
</cxx-function>
265+
</cxx-section>
266+
267+
<cxx-section id="parallel.task_block.exceptions">
268+
<h1>Exception Handling</h1>
269+
270+
<p>
271+
Every <code>task_block</code> has an associated exception list. When the task block starts, its associated exception list is empty.
272+
</p>
273+
274+
<p>
275+
When an exception is thrown from the user-provided function object passed to <code>define_task_block</code> or
276+
<code>define_task_block_restore_thread</code>, it is added to the exception list for that task block. Similarly, when
277+
an exception is thrown from the user-provided function object passed into <code>task_block::run</code>, the exception
278+
object is added to the exception list associated with the nearest enclosing task block. In both cases, an
279+
implementation may discard any pending tasks that have not yet been invoked. Tasks that are already in
280+
progress are not interrupted except at a call to <code>task_block::run</code> or <code>task_block::wait</code> as described below.
281+
</p>
282+
283+
<p>
284+
If the implementation is able to detect that an exception has been thrown by another task within
285+
the same nearest enclosing task block, then <code>task_block::run</code> or <code>task_block::wait</code> may throw
286+
<code>task_canceled_exception</code>; these instances of <code>task_canceled_exception</code> are not added to the exception
287+
list of the corresponding task block.
288+
</p>
289+
290+
<p>
291+
When a task block finishes with a non-empty exception list, the exceptions are aggregated into an <code>exception_list</code> object, which is then thrown from the task block.
292+
</p>
293+
294+
<p>
295+
The order of the exceptions in the <code>exception_list</code> object is unspecified.
296+
</p>
297+
</cxx-section>
298+
</cxx-clause>
299+
</ins>
300+

0 commit comments

Comments
 (0)