|
4382 | 4382 | });
|
4383 | 4383 | \end{codeblock}
|
4384 | 4384 |
|
| 4385 | +\rSec2[exec.consumers]{Sender consumers} |
| 4386 | + |
| 4387 | +\rSec3[exec.sync.wait]{\tcode{this_thread::sync_wait}} |
| 4388 | + |
| 4389 | +\pnum |
| 4390 | +\tcode{this_thread::sync_wait} and \tcode{this_thread::sync_wait_with_variant} |
| 4391 | +are used |
| 4392 | +to block the current thread of execution |
| 4393 | +until the specified sender completes and |
| 4394 | +to return its async result. |
| 4395 | +\tcode{sync_wait} mandates |
| 4396 | +that the input sender has exactly one value completion signature. |
| 4397 | + |
| 4398 | +\pnum |
| 4399 | +Let \exposid{sync-wait-env} be the following exposition-only class type: |
| 4400 | +\begin{codeblock} |
| 4401 | +namespace std::this_thread { |
| 4402 | + struct @\exposid{sync-wait-env}@ { |
| 4403 | + execution::run_loop* @\exposid{loop}@; // \expos |
| 4404 | + |
| 4405 | + auto query(execution::get_scheduler_t) const noexcept { |
| 4406 | + return @\exposid{loop}@->get_scheduler(); |
| 4407 | + } |
| 4408 | + |
| 4409 | + auto query(execution::get_delegation_scheduler_t) const noexcept { |
| 4410 | + return @\exposid{loop}@->get_scheduler(); |
| 4411 | + } |
| 4412 | + }; |
| 4413 | +} |
| 4414 | +\end{codeblock} |
| 4415 | + |
| 4416 | +\pnum |
| 4417 | +Let \exposid{sync-wait-result-type} and |
| 4418 | +\exposid{sync-wait-with-variant-result-type} |
| 4419 | +be exposition-only alias templates defined as follows: |
| 4420 | +\begin{codeblock} |
| 4421 | +namespace std::this_thread { |
| 4422 | + template<execution::@\libconcept{sender_in}@<@\exposid{sync-wait-env}@> Sndr> |
| 4423 | + using sync-wait-result-type = |
| 4424 | + optional<execution::value_types_of_t<Sndr, @\exposid{sync-wait-env}@, @\exposid{decayed-tuple}@, |
| 4425 | + type_identity_t>>; |
| 4426 | + |
| 4427 | + template<execution::sender_in<sync-wait-env> Sndr> |
| 4428 | + using @\exposid{sync-wait-with-variant-result-type}@ = |
| 4429 | + optional<execution::value_types_of_t<Sndr, @\exposid{sync-wait-env}@>>; |
| 4430 | +} |
| 4431 | +\end{codeblock} |
| 4432 | + |
| 4433 | +\pnum |
| 4434 | +The name \tcode{this_thread::sync_wait} denotes a customization point object. |
| 4435 | +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. |
| 4436 | +If \tcode{\libconcept{sender_in}<Sndr, \exposid{sync-wait-env}>} |
| 4437 | +is \tcode{false}, |
| 4438 | +the expression \tcode{this_thread::sync_wait(sndr)} is ill-formed. |
| 4439 | +Otherwise, it is expression-equivalent to the following, |
| 4440 | +except that \tcode{sndr} is evaluated only once: |
| 4441 | +\begin{codeblock} |
| 4442 | +apply_sender(@\exposid{get-domain-early}@(sndr), sync_wait, sndr) |
| 4443 | +\end{codeblock} |
| 4444 | +\mandates |
| 4445 | +\begin{itemize} |
| 4446 | +\item |
| 4447 | +The type \tcode{\exposid{sync-wait-result-type}<Sndr>} is well-formed. |
| 4448 | +\item |
| 4449 | +\tcode{\libconcept{same_as}<decltype($e$), \exposid{sync-wait-result-type}<Sndr>>} |
| 4450 | +is \tcode{true}, where $e$ is the apply_sender expression above. |
| 4451 | +\end{itemize} |
| 4452 | + |
| 4453 | +\pnum |
| 4454 | +Let \exposid{sync-wait-state} and \exposid{sync-wait-receiver} |
| 4455 | +be the following exposition-only class templates: |
| 4456 | +\begin{codeblock} |
| 4457 | +namespace std::this_thread { |
| 4458 | + template<class Sndr> |
| 4459 | + struct @\exposid{sync-wait-state}@ { // \expos |
| 4460 | + execution::run_loop @\exposid{loop}@; // \expos |
| 4461 | + exception_ptr @\exposid{error}@; // \expos |
| 4462 | + @\exposid{sync-wait-result-type}@<Sndr> @\exposid{result}@; // \expos |
| 4463 | + }; |
| 4464 | + |
| 4465 | + template<class Sndr> |
| 4466 | + struct @\exposid{sync-wait-receiver}@ { // \expos |
| 4467 | + using receiver_concept = execution::receiver_t; |
| 4468 | + @\exposid{sync-wait-state}@<Sndr>* @\exposid{state}@; // \expos |
| 4469 | + |
| 4470 | + template<class... Args> |
| 4471 | + void set_value(Args&&... args) && noexcept; |
| 4472 | + |
| 4473 | + template<class Error> |
| 4474 | + void set_error(Error&& err) && noexcept; |
| 4475 | + |
| 4476 | + void set_stopped() && noexcept; |
| 4477 | + |
| 4478 | + @\exposid{sync-wait-env}@ get_env() const noexcept { return {&@\exposid{state}@->@\exposid{loop}@}; } |
| 4479 | + }; |
| 4480 | +} |
| 4481 | +\end{codeblock} |
| 4482 | + |
| 4483 | +\begin{itemdecl} |
| 4484 | +template<class... Args> |
| 4485 | +void set_value(Args&&... args) && noexcept; |
| 4486 | +\end{itemdecl} |
| 4487 | + |
| 4488 | +\begin{itemdescr} |
| 4489 | +\pnum |
| 4490 | +\effects |
| 4491 | +Equivalent to: |
| 4492 | +\begin{codeblock} |
| 4493 | +try { |
| 4494 | + @\exposid{state}@->@\exposid{result}@.emplace(std::forward<Args>(args)...); |
| 4495 | +} catch (...) { |
| 4496 | + @\exposid{state}@->@\exposid{error}@ = current_exception(); |
| 4497 | +} |
| 4498 | +@\exposid{state}@->@\exposid{loop}@.finish(); |
| 4499 | +\end{codeblock} |
| 4500 | +\end{itemdescr} |
| 4501 | + |
| 4502 | +\begin{itemdecl} |
| 4503 | +template<class Error> |
| 4504 | +void set_error(Error&& err) && noexcept; |
| 4505 | +\end{itemdecl} |
| 4506 | + |
| 4507 | +\begin{itemdescr} |
| 4508 | +\pnum |
| 4509 | +\effects |
| 4510 | +Equivalent to: |
| 4511 | +\begin{codeblock} |
| 4512 | +@\exposid{state}@->@\exposid{error}@ = @\exposid{AS-EXCEPT-PTR}@(std::forward<Error>(err)); // see \ref{exec.general} |
| 4513 | +@\exposid{state}@->@\exposid{loop}@.finish(); |
| 4514 | +\end{codeblock} |
| 4515 | +\end{itemdescr} |
| 4516 | + |
| 4517 | +\begin{itemdecl} |
| 4518 | +void set_stopped() && noexcept; |
| 4519 | +\end{itemdecl} |
| 4520 | + |
| 4521 | +\begin{itemdescr} |
| 4522 | +\pnum |
| 4523 | +\effects |
| 4524 | +Equivalent to \tcode{\exposid{state}->\exposid{loop}.finish()}. |
| 4525 | +\end{itemdescr} |
| 4526 | + |
| 4527 | +\pnum |
| 4528 | +For a subexpression \tcode{sndr}, let \tcode{Sndr} be \tcode{decltype((sndr))}. |
| 4529 | +If \tcode{\exposconcept{sender_to}<Sndr, \exposid{sync-wait-receiver}<\linebreak Sndr>>} |
| 4530 | +is \tcode{false}, |
| 4531 | +the expression \tcode{sync_wait.apply_sender(sndr)} is ill-formed; |
| 4532 | +otherwise, it is equivalent to: |
| 4533 | +\begin{codeblock} |
| 4534 | +@\exposid{sync-wait-state}@<Sndr> state; |
| 4535 | +auto op = connect(sndr, @\exposid{sync-wait-receiver}@<Sndr>{&state}); |
| 4536 | +start(op); |
| 4537 | + |
| 4538 | +state.@\exposid{loop}@.run(); |
| 4539 | +if (state.@\exposid{error}@) { |
| 4540 | + rethrow_exception(std::move(state.error)); |
| 4541 | +} |
| 4542 | +return std::move(state.@\exposid{result}@); |
| 4543 | +\end{codeblock} |
| 4544 | + |
| 4545 | +\pnum |
| 4546 | +The behavior of \tcode{this_thread::sync_wait(sndr)} is undefined unless: |
| 4547 | +\begin{itemize} |
| 4548 | +\item |
| 4549 | +It blocks the current thread of execution\iref{defns.block} |
| 4550 | +with forward progress guarantee delegation\iref{intro.progress} |
| 4551 | +until the specified sender completes. |
| 4552 | +\begin{note} |
| 4553 | +The default implementation of \tcode{sync_wait} achieves |
| 4554 | +forward progress guarantee delegation by providing a \tcode{run_loop} scheduler |
| 4555 | +via the \tcode{get_delegation_scheduler} query |
| 4556 | +on the \exposid{sync-wait-receiver}'s environment. |
| 4557 | +The \tcode{run_loop} is driven by the current thread of execution. |
| 4558 | +\end{note} |
| 4559 | +\item |
| 4560 | +It returns the specified sender's async results as follows: |
| 4561 | +\begin{itemize} |
| 4562 | +\item |
| 4563 | +For a value completion, |
| 4564 | +the result datums are returned in |
| 4565 | +a \tcode{tuple} in an engaged \tcode{optional} object. |
| 4566 | +\item |
| 4567 | +For an error completion, an exception is thrown. |
| 4568 | +\item |
| 4569 | +For a stopped completion, a disengaged \tcode{optional} object is returned. |
| 4570 | +\end{itemize} |
| 4571 | +\end{itemize} |
| 4572 | + |
| 4573 | +\rSec3[exec.sync.wait.var]{\tcode{this_thread::sync_wait_with_variant}} |
| 4574 | + |
| 4575 | +\pnum |
| 4576 | +The name \tcode{this_thread::sync_wait_with_variant} denotes |
| 4577 | +a customization point object. |
| 4578 | +For a subexpression \tcode{sndr}, |
| 4579 | +let \tcode{Sndr} be \tcode{decltype(into_variant(sndr))}. |
| 4580 | +If \tcode{\libconcept{sender_in}<Sndr, \exposid{sync-wait-env}>} |
| 4581 | +is \tcode{false}, |
| 4582 | +\tcode{this_thread::sync_wait_with_variant(sndr)} is ill-formed. |
| 4583 | +Otherwise, it is expression-equivalent to the following, |
| 4584 | +except \tcode{sndr} is evaluated only once: |
| 4585 | +\begin{codeblock} |
| 4586 | +apply_sender(@\exposid{get-domain-early}@(sndr), sync_wait_with_variant, sndr) |
| 4587 | +\end{codeblock} |
| 4588 | +\mandates |
| 4589 | +\begin{itemize} |
| 4590 | +\item |
| 4591 | +The type \tcode{\exposid{sync-wait-with-variant-result-type}<Sndr>} |
| 4592 | +is well-formed. |
| 4593 | +\item |
| 4594 | +\tcode{\libconcept{same_as}<decltype($e$), \exposid{sync-wait-with-variant-result-type}<Sndr>>} |
| 4595 | +is \tcode{true}, where $e$ is the \tcode{ap\-ply_sender} expression above. |
| 4596 | +\end{itemize} |
| 4597 | + |
| 4598 | +\pnum |
| 4599 | +If \tcode{\exposconcept{callable}<sync_wait_t, Sndr>} is \tcode{false}, |
| 4600 | +the expression \tcode{sync_wait_with_variant.apply_sender(\linebreak sndr)} is ill-formed. |
| 4601 | +Otherwise, it is equivalent to: |
| 4602 | +\begin{codeblock} |
| 4603 | +using result_type = @\exposid{sync-wait-with-variant-result-type}@<Sndr>; |
| 4604 | +if (auto opt_value = sync_wait(into_variant(sndr))) { |
| 4605 | + return result_type(std::move(get<0>(*opt_value))); |
| 4606 | +} |
| 4607 | +return result_type(nullopt); |
| 4608 | +\end{codeblock} |
| 4609 | + |
| 4610 | +\pnum |
| 4611 | +The behavior of \tcode{this_thread::sync_wait_with_variant(sndr)} |
| 4612 | +is undefined unless: |
| 4613 | +\begin{itemize} |
| 4614 | +\item |
| 4615 | +It blocks the current thread of execution\iref{defns.block} |
| 4616 | +with forward progress guarantee delegation\iref{intro.progress} |
| 4617 | +until the specified sender completes. |
| 4618 | +\begin{note} |
| 4619 | +The default implementation of \tcode{sync_wait_with_variant} achieves |
| 4620 | +forward progress guarantee delegation by relying on |
| 4621 | +the forward progress guarantee delegation provided by \tcode{sync_wait}. |
| 4622 | +\end{note} |
| 4623 | +\item |
| 4624 | +It returns the specified sender's async results as follows: |
| 4625 | +\begin{itemize} |
| 4626 | +\item |
| 4627 | +For a value completion, |
| 4628 | +the result datums are returned in an engaged \tcode{optional} object |
| 4629 | +that contains a \tcode{variant} of \tcode{tuple}s. |
| 4630 | +\item |
| 4631 | +For an error completion, an exception is thrown. |
| 4632 | +\item |
| 4633 | +For a stopped completion, a disengaged \tcode{optional} object is returned. |
| 4634 | +\end{itemize} |
| 4635 | +\end{itemize} |
| 4636 | + |
4385 | 4637 | \rSec1[exec.util]{Sender/receiver utilities}
|
4386 | 4638 |
|
4387 | 4639 | \rSec1[exec.ctx]{Execution contexts}
|
|
0 commit comments