[#design:race] == Race The most important synchronization mechanism is the `race` function. It awaits multiple <>s in a pseudo-random order and will return the result of the first one completion, before disregarding the rest. That is, it initiates the `co_await` in a pseudo-random order and stops once one awaitable is found to be ready or completed immediately. [source,cpp] ---- cobalt::generator gen1(); cobalt::generator gen2(); cobalt::promise p() { auto g1 = gen1(); auto g2 = gen2(); while (!co_await cobalt::this_coro::cancelled) { switch(auto v = co_await race(g1, g2); v.index()) { case 0: printf("Got int %d\n", get<0>(v)); break; case 1: printf("Got double %f\n", get<1>(v)); break; } } } ---- The `race` must however internally wait for all awaitable to complete once it initiates to `co_await`. Therefore, once the first <> completes, it tries to <> the rest, and if that fails cancels them. `race` is the preferred way to trigger cancellations, e.g.: [source,cpp] ---- cobalt::promise timeout(); cobalt::promise work(); race(timeout(), work()); ---- [#design:interrupt_await] == interrupt_await If it naively cancelled it would however lose data. Thus, the concept of `interrupt_await` is introduced, which tells the awaitable (that supports it) to immediately resume the awaiter and return or throw an ignored value. .Example of an interruptible awaitable [source,cpp] ---- struct awaitable { bool await_ready() const; template std::coroutine_handle await_suspend(std::coroutine_handle h); T await_resume(); void interrupt_await() &; }; ---- If the `interrupt_await` doesn't result in immediate resumption (of `h`), `race` will send a cancel signal. `race` applies these with the correct reference qualification: [source,cpp] ---- auto g = gen1(); race(g, gen2()); ---- The above will call a `interrupt_await() &` function for `g1` and `interrupt_await() &&` for `g2` if available. NOTE: Generally speaking, the coroutines in `cobalt` support lvalue interruption, i.e. `interrupt_await() &`. <> operations are unqualified, i.e. work in both cases. <> and <> will forward interruptions, i.e. this will only interrupt `g1` and `g2` if `gen2()` completes first: