diff --git a/source/elements/oneTBB/source/algorithms/functions/parallel_for_each_func.rst b/source/elements/oneTBB/source/algorithms/functions/parallel_for_each_func.rst index 0469c277b5..57de97b64e 100644 --- a/source/elements/oneTBB/source/algorithms/functions/parallel_for_each_func.rst +++ b/source/elements/oneTBB/source/algorithms/functions/parallel_for_each_func.rst @@ -37,12 +37,13 @@ Function template that processes work items in parallel. Requirements: * The ``Body`` type must meet the :doc:`ParallelForEachBody requirements <../../named_requirements/algorithms/par_for_each_body>`. - Since C++17, ``Body`` may also be a pointer to a member function in ``Index``. + Since C++17, ``Body`` may also be a pointer to a member function in ``std::iterator_traits::value_type``. * The ``InputIterator`` type must meet the `Input Iterator` requirements from the [input.iterators] section of the ISO C++ Standard. * If ``InputIterator`` type does not meet the `Forward Iterator` requirements from the [forward.iterators] section of the ISO C++ Standard, the ``std::iterator_traits::value_type`` type must be constructible from ``std::iterator_traits::reference``. * The ``Container`` type must meet the :doc:`ContainerBasedSequence requirements <../../named_requirements/algorithms/container_based_sequence>`. -* The type returned by ``Container::begin()`` must meet the same requirements as the ``InputIterator`` type above. +* The type returned by ``std::begin`` and ``std::end`` applied to a ``Container`` object + must meet the same requirements as the ``InputIterator`` type above. The ``parallel_for_each`` template has two forms. diff --git a/source/elements/oneTBB/source/named_requirements.rst b/source/elements/oneTBB/source/named_requirements.rst index e134f6fd19..4133464b4d 100644 --- a/source/elements/oneTBB/source/named_requirements.rst +++ b/source/elements/oneTBB/source/named_requirements.rst @@ -10,9 +10,9 @@ Named Requirements This section describes named requirements used in the oneTBB Specification. A *named requirement* is a set of requirements on a type. The requirements may be syntactic or semantic. -The *named_requirement* term is similar to “Requirements on types and expressions” term which is defined -by the ISO C++ Standard (chapter “Library Introduction”) or `“Named Requirements” section `_ -on the cppreference.com site. +The *named requirement* term is similar to “Requirements on types and expressions” term which is defined +by the ISO C++ Standard (chapter “Library Introduction”) or +`“Named Requirements” section `_ on the cppreference.com site. For example, the named requirement of *sortable* could be defined as a set of requirements that enable an array to be sorted. A type ``T`` would be *sortable* if: @@ -22,11 +22,22 @@ an array to be sorted. A type ``T`` would be *sortable* if: You can write a sorting template function in C++ that sorts an array of any type that is *sortable*. +.. _pseudo_signatures: + +Pseudo-Signatures +----------------- + Two approaches for defining named requirements are *valid expressions* and *pseudo-signatures*. -The ISO C++ standard follows the valid *expressions* approach, which shows what the usage pattern looks like for a requirement. -It has the drawback of relegating important details to notational conventions. This document uses +The ISO C++ standard follows the *valid expressions* approach, which shows what the usage pattern looks like for a requirement. +It has the drawback of relegating important details to notational conventions. This document mostly uses pseudo-signatures because they are concise and can be cut-and-pasted for an initial implementation. +A pseudo-signature describes how an implementation interacts with a type or a function. +A real function signature (after template instantiation, if applicable) may differ from the pseudo-signature +that it implements in ways where implicit conversions would deal with the difference, +transforming function parameter types from the ones in the pseudo-signature to the real signature, +and transforming the actual return value type to the one in the pseudo-signature. + For example, the table below shows pseudo-signatures for a *sortable* type ``T``: --------------------------------------------------------------------------------------------- @@ -35,20 +46,49 @@ For example, the table below shows pseudo-signatures for a *sortable* type ``T`` .. cpp:function:: bool operator<(const T& x, const T& y) - Compare x and y. + Compare ``x`` and ``y``. .. cpp:function:: void swap(T& x, T& y) - Swap x and y. + Swap ``x`` and ``y``. --------------------------------------------------------------------------------------------- -A real signature may differ from the pseudo-signature that it implements in ways where implicit -conversions would deal with the difference. For an example type ``U``, the real signature that -implements ``operator<`` in the table above can be expressed as ``int operator<( U x, U y )``, -because C++ permits implicit conversion from ``int`` to ``bool``, and implicit conversion from ``U`` -to (``const U&``). Similarly, the real signature ``bool operator<( U& x, U& y )`` is acceptable -because C++ permits implicit addition of a const qualifier to a reference type. +For a given type ``U``, the real signature that implements ``operator<`` in the table above +can be expressed as ``int operator<( U x, U y )``, because C++ permits implicit conversion from +``int`` to ``bool``, and implicit conversion from ``const U&`` to ``U`` if the type is copy-constructible. +As a counter-example, the real signature ``bool operator<( U& x, U& y )`` is not acceptable +because C++ does not permit implicit removal of the ``const`` qualifier from a type, and so the code +would not compile if the implementation attempts to pass a constant object to the function. + +Besides pseudo-signatures, semantic requirements also need to be met by real types and functions. +For example, while ``std::pair swap(U x, U y)`` fits the pseudo-signature for *Sortable* +via implicit conversion of references to values and implicit drop of the returned value +(ignored by a library implementation), it is unable to swap the actual variables passed to the function +and therefore does not meet the semantic requirements of *Sortable*. + +The following table provides guidance for the types of parameters used in pseudo-signatures +and potential alternatives in real signatures. In practice, suitable alternatives might depend +on the semantic requirements as well as type properties, such as availability of copy- or move-constructors. + +========================== ================================ ============================= +Pseudo-signature parameter General semantics Alternative real parameters +========================== ================================ ============================= +``const T& a`` The function is not supposed - ``T a`` + to modify the argument. - ``X& a``, ``auto& a`` + - ``X&& a``, ``auto&& a`` + + Here and below ``X`` is a template type parameter. + +``T& a`` The argument is an lvalue. - ``const T& a`` + The function can or is - ``T a`` + supposed to modify the argument. - ``X& a``, ``auto& a`` + - ``X&& a``, ``auto&& a`` + +``T&& a`` The argument is an rvalue. The - ``const T& a`` + function can use the argument - ``T a`` + as a source in move operations. - ``X&& a``, ``auto&& a`` +========================== ================================ ============================= Algorithms ---------- @@ -81,7 +121,6 @@ Mutexes Containers ---------- - .. toctree:: :titlesonly: diff --git a/source/elements/oneTBB/source/named_requirements/algorithms/container_based_sequence.rst b/source/elements/oneTBB/source/named_requirements/algorithms/container_based_sequence.rst index e46490e274..c00435e675 100644 --- a/source/elements/oneTBB/source/named_requirements/algorithms/container_based_sequence.rst +++ b/source/elements/oneTBB/source/named_requirements/algorithms/container_based_sequence.rst @@ -7,25 +7,27 @@ ContainerBasedSequence ====================== **[req.container_based_sequence]** -A type `C` satisfies `ContainerBasedSequence` if it meets the following requirements: +A type `C` satisfies `ContainerBasedSequence` if the following expressions are valid +for a (possibly const) object ``c`` of the type `C`: ---------------------------------------------------------------- -**ContainerBasedSequence Requirements: Pseudo-Signature, Semantics** +**ContainerBasedSequence Requirements: Expression, Semantics** - .. note:: +.. cpp:function:: std::begin(c) - In this page ``c`` is an object of type (possibly ``const``) ``C``. + Returns an iterator to the beginning of the sequence represented by ``c``. - Templates that use the named requirement can impose stricter requirements on the iterator concept. +.. cpp:function:: std::end(c) -.. cpp:function:: std::begin(c) + Returns an iterator one past the end of the sequence represented by ``c``. - Returns an input iterator to the beginning of the sequence represented by ``c``. +---------------------------------------------------------------- -.. cpp:function:: std::end(c) +.. note:: - Returns an input iterator one past the end of the sequence represented by ``c``. + The category of an iterator returned by ``std::begin``/``std::end`` is determined by + a template that uses `ContainerBasedSequence`. See also: diff --git a/source/elements/oneTBB/source/named_requirements/algorithms/par_for_each_body.rst b/source/elements/oneTBB/source/named_requirements/algorithms/par_for_each_body.rst index 8abfcbb498..9ea453340c 100644 --- a/source/elements/oneTBB/source/named_requirements/algorithms/par_for_each_body.rst +++ b/source/elements/oneTBB/source/named_requirements/algorithms/par_for_each_body.rst @@ -7,54 +7,44 @@ ParallelForEachBody =================== **[req.parallel_for_each_body]** -A type `Body` satisfies `ParallelForBody` if it meets the `Function Objects` -requirements described in the [function.objects] section of the ISO C++ standard. -It should also meet one of the following requirements: +A type `Body` satisfies `ParallelForEachBody` if it meets the `Function Objects` +requirements described in the [function.objects] section of the ISO C++ standard, +as well as meets exactly one of the following two alternative requirements for ``operator()``: ---------------------------------------------------------------- **ParallelForEachBody Requirements: Pseudo-Signature, Semantics** -.. cpp:function:: Body::operator()( ItemType item ) const +Alternative 1: - Process the received item. - -.. cpp:function:: Body::operator()( ItemType item, oneapi::tbb::feeder& feeder ) const - - Process the received item. May invoke the ``feeder.add(T)`` function to spawn additional items. - ------------------------------------------------------------------ +.. cpp:function:: void Body::operator()( ReferenceType item ) const -.. note:: + Process the received item. - ``ItemType`` may be optionally passed to ``Body::operator()`` by reference. - ``const`` and ``volatile`` type qualifiers are also applicable. +---------------------------------------------------------------- -Terms ------ +Alternative 2: -* ``iterator`` determines the type of the iterator passed into the ``parallel_for_each`` algorithm, - which is ``decltype(std::begin(c))`` for the overloads that accept the ``Container`` template argument or ``InputIterator``. -* ``value_type`` - the type ``std::iterator_traits::value_type``. -* ``reference`` - the type ``std::iterator_traits::reference``. +.. cpp:function:: void Body::operator()( ReferenceType item, oneapi::tbb::feeder& feeder ) const + void Body::operator()( ItemType&& item, oneapi::tbb::feeder& feeder ) const -``oneapi::tbb::parallel_for_each`` requires the ``Body::operator()`` call with an object of the ``reference`` type to be well-formed if -the ``iterator`` meets the `Forward iterator` requirements described in the [forward.iterators] section of the -ISO C++ Standard. + Process the received item. May invoke the ``feeder.add`` function to spawn additional items. + The ``Body::operator()`` must accept both ``ReferenceType`` and ``ItemType&&`` values as the first argument. -`oneapi::tbb::parallel_for_each algorithm <../../algorithms/functions/parallel_for_each_func>`_ -requires the ``Body::operator()`` call with an object of type ``const value_type&`` or ``value_type&&`` to be well-formed if following requirements are met: +----------------------------------------------------------------- -* the iterator meets the `Input iterator` requirements described in the [input.iterators] section of the ISO C++ Standard -* the iterator does not meet the `Forward iterator` requirements described in the [forward.iterators] section of the ISO C++ Standard +where -.. caution:: +* ``ItemType`` is ``std::iterator_traits::value_type`` for the type of the iterator + the ``parallel_for_each`` algorithm operates with, and +* ``ReferenceType`` is ``std::iterator_traits::reference`` if the iterator type is + a `forward iterator` as described in the [forward.iterators] section of the ISO C++ Standard, +* otherwise, ``ReferenceType`` is ``ItemType&&``. - If the ``Body`` only takes non-const lvalue reference to the ``value_type``, the requirements described above - are violated, and the program can be ill-formed. +.. note:: -Additional elements submitted into ``oneapi::tbb::parallel_for_each`` through the ``feeder::add`` are passed to the ``Body`` as rvalues. In this case, the corresponding -execution of the ``Body`` is required to be well-formed. + The usual rules for :ref:`pseudo-signatures ` apply. + Therefore, ``Body::operator()`` may optionally take items by value or by ``const`` reference. See also: diff --git a/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_body.rst b/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_body.rst index 15f098a362..09375fa99a 100644 --- a/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_body.rst +++ b/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_body.rst @@ -34,4 +34,4 @@ A type `Body` satisfies `ParallelReduceBody` if it meets the following requireme See also: * :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>` -* :doc:`parallel_determinstic_reduce algorithm <../../algorithms/functions/parallel_deterministic_reduce_func>` +* :doc:`parallel_deterministic_reduce algorithm <../../algorithms/functions/parallel_deterministic_reduce_func>` diff --git a/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_func.rst b/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_func.rst index 8845dfd771..e4e81e1031 100644 --- a/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_func.rst +++ b/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_func.rst @@ -5,7 +5,7 @@ ================== ParallelReduceFunc ================== -**[req.parallel_reduce_body]** +**[req.parallel_reduce_func]** A type `Func` satisfies `ParallelReduceFunc` if it meets the following requirements: @@ -13,14 +13,14 @@ A type `Func` satisfies `ParallelReduceFunc` if it meets the following requireme **ParallelReduceFunc Requirements: Pseudo-Signature, Semantics** -.. cpp:function:: Value Func::operator()(const Range& range, const Value& x) const +.. cpp:function:: Value Func::operator()(const Range& range, Value&& x) const - Accumulates result for a subrange, starting with initial value ``x``. - ``Range`` type must meet the :doc:`Range requirements `. - ``Value`` type must be the same as a corresponding template parameter for the - :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>` algorithm. + Accumulates values over ``range``, starting with the initial value ``x``. + The ``Range`` type must meet the :doc:`Range requirements `. + The ``Value`` type must be the same as the corresponding template parameter for the + :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>`. See also: * :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>` -* :doc:`parallel_determinstic_reduce algorithm <../../algorithms/functions/parallel_deterministic_reduce_func>` +* :doc:`parallel_deterministic_reduce algorithm <../../algorithms/functions/parallel_deterministic_reduce_func>` diff --git a/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_reduction.rst b/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_reduction.rst index c65c34c2c9..e5c3efd8c5 100644 --- a/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_reduction.rst +++ b/source/elements/oneTBB/source/named_requirements/algorithms/par_reduce_reduction.rst @@ -13,13 +13,13 @@ A type `Reduction` satisfies `ParallelReduceReduction` if it meets the following **ParallelReduceReduction Requirements: Pseudo-Signature, Semantics** -.. cpp:function:: Value Reduction::operator()(const Value& x, const Value& y) const +.. cpp:function:: Value Reduction::operator()(Value&& x, Value&& y) const - Combines results ``x`` and ``y``. - ``Value`` type must be the same as a corresponding template parameter for the - :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>` algorithm. + Combines the results ``x`` and ``y``. + The ``Value`` type must be the same as the corresponding template parameter for the + :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>`. See also: * :doc:`parallel_reduce algorithm <../../algorithms/functions/parallel_reduce_func>` -* :doc:`parallel_determinstic_reduce algorithm <../../algorithms/functions/parallel_deterministic_reduce_func>` +* :doc:`parallel_deterministic_reduce algorithm <../../algorithms/functions/parallel_deterministic_reduce_func>`