mirror of
https://github.com/boostorg/cobalt.git
synced 2026-01-24 05:42:13 +00:00
122 lines
4.1 KiB
Plaintext
122 lines
4.1 KiB
Plaintext
[#race]
|
|
== cobalt/race.hpp
|
|
|
|
The `race` function can be used to `co_await` one <<awaitable, awaitable>> out of a set of them.
|
|
|
|
It can be called as a variadic function with multiple <<awaitable, awaitable>> or as on a range of <<awaitable, awaitables>>.
|
|
|
|
[source,cpp]
|
|
----
|
|
cobalt::promise<void> task1();
|
|
cobalt::promise<void> task2();
|
|
|
|
cobalt::promise<void> do_wait()
|
|
{
|
|
co_await cobalt::race(task1(), task2()); // <1>
|
|
std::vector<cobalt::promise<void>> aws {task1(), task2()};
|
|
co_await cobalt::race(aws); // <2>
|
|
}
|
|
----
|
|
<1> Wait for a variadic set of <<awaitable, awaitables>>
|
|
<2> wait for a vector of <<awaitable, awaitables>>
|
|
|
|
The first parameter so `race` can be a https://en.cppreference.com/w/cpp/named_req/UniformRandomBitGenerator[uniform random bit generator].
|
|
|
|
|
|
.Signatures of race
|
|
[source, cpp]
|
|
----
|
|
extern promise<void> pv1, pv2;
|
|
std::vector<promise<void>> pvv;
|
|
|
|
std::default_random_engine rdm{1};
|
|
// if everything returns void race returns the index
|
|
std::size_t r1 = co_await race(pv1, pv2);
|
|
std::size_t r2 = co_await race(rdm, pv1, pv2);
|
|
std::size_t r3 = co_await race(pvv);
|
|
std::size_t r4 = co_await race(rdm, pvv);
|
|
|
|
// variant if not everything is void. void become monostate
|
|
extern promise<int> pi1, pi2;
|
|
variant2::variant<monostate, int, int> r5 = co_await race(pv1, pi1, pi2);
|
|
variant2::variant<monostate, int, int> r6 = co_await race(rdm, pv1, pi1, pi2);
|
|
|
|
// a range returns a pair of the index and the result if non-void
|
|
std::vector<promise<int>> piv;
|
|
std::pair<std::size_t, int> r7 = co_await race(piv);
|
|
std::pair<std::size_t, int> r8 = co_await race(rdm, piv);
|
|
----
|
|
|
|
[#interrupt_await]
|
|
=== Interrupt Wait
|
|
|
|
When arguments are passed as rvalue reference, the race will attempt to use `.interrupt_await`
|
|
on the <<awaitable, awaitable>> to signal the awaitable to complete now and that the result will be ignored.
|
|
If supported, the <<awaitable>> must resume the awaiting coroutine before `interrupt_await` returns.
|
|
If the `race` doesn't detect the function, it will send a cancellation.
|
|
|
|
This means that you can reuse race like this:
|
|
|
|
[source,cpp]
|
|
----
|
|
|
|
cobalt::promise<void> do_wait()
|
|
{
|
|
auto t1 = task1();
|
|
auto t2 = task2();
|
|
co_await cobalt::race(t1, t2); // <1>
|
|
co_await cobalt::race(t1, t2); // <2>
|
|
}
|
|
----
|
|
<1> Wait for the first task to complete
|
|
<2> Wait for the other task to complete
|
|
|
|
This is supported by <<promise, promise>>, <<generator, generator>> and <<gather, gather>>.
|
|
|
|
The `race` will invoke the functions of the `awaitable` as if used in a `co_await` expression
|
|
or not evaluate them at all.
|
|
|
|
[#left_race]
|
|
=== `left_race`
|
|
|
|
The `left_race` functions are like `race` but follow a strict left-to-right scan.
|
|
This can lead to starvation issues, which is why this is not the recommended default, but can
|
|
be useful for prioritization if proper care is taken.
|
|
|
|
|
|
[#race-outline]
|
|
=== Outline
|
|
|
|
[source,cpp,subs=+quotes]
|
|
----
|
|
// Concept for the random number generator.
|
|
include::../../include/boost/cobalt/race.hpp[tag=concept]
|
|
|
|
// Variadic race with a custom random number generator
|
|
template<asio::cancellation_type Ct = asio::cancellation_type::all,
|
|
uniform_random_bit_generator URBG, awaitable ... Promise>
|
|
__awaitable__ race(URBG && g, Promise && ... p);
|
|
|
|
// Ranged race with a custom random number generator
|
|
template<asio::cancellation_type Ct = asio::cancellation_type::all,
|
|
uniform_random_bit_generator URBG, range<awaitable> PromiseRange>
|
|
__awaitable__ race(URBG && g, PromiseRange && p);
|
|
|
|
// Variadic race with the default random number generator
|
|
template<asio::cancellation_type Ct = asio::cancellation_type::all, awaitable... Promise>
|
|
__awaitable__ race(Promise && ... p);
|
|
|
|
// Ranged race with the default random number generator
|
|
template<asio::cancellation_type Ct = asio::cancellation_type::all, range<awaitable>>
|
|
__awaitable__ race(PromiseRange && p);
|
|
|
|
// Variadic left race
|
|
template<asio::cancellation_type Ct = asio::cancellation_type::all, awaitable... Promise>
|
|
__awaitable__ left_race(Promise && ... p);
|
|
|
|
// Ranged left race
|
|
template<asio::cancellation_type Ct = asio::cancellation_type::all, range<awaitable>>
|
|
__awaitable__ left_race(PromiseRange && p);
|
|
----
|
|
|
|
NOTE: Selecting an empty range will cause an exception to be thrown. |