1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
So far we've encountered tt(co_yield) and tt(co_return). What about
tt(co_await)? The verb em(to await) is more formal than em(to wait), but the
two verbs mean the same. The added level of formality of em(to await) is
illustrated by a second description offered by the em(Merrian Webster)
dictionary: em(to remain in abeyance until), and em(abeyance's) meaning takes
us home again: em(a state of temporary inactivity) or em(suspension). So when
tt(co_await) is used the coroutine enters a state of temporary inactivity,
i.e., it is suspended. In that sense tt(co_yield) is no different, as it also
suspends the coroutine, but different from tt(co_yield co_await) expects a
so-called emi(awaitable) expression. I.e., an expression resulting in an
tt(Awaitable), or that is convertible to an tt(Awaitable)
object (see also figure ref(CoAwaitFig)).
figure(coroutines/coawait)
(co_await)
(CoAwaitFig)
Figure ref(CoAwaitFig) shows that the expression that's passed to
tt(co_await) may be an tt(Awaitable) object, or if the coroutine handle's
tt(State) class has a member ti(await_transform) accepting an argument of some
tt(expr's) type, the value returned by tt(await_transform) is the tt(
Awaitable) (cf. figure ref(AwaitableFig)). These tt(await_transform) members
may be overloaded, so in any concrete situation several tt(Awaitable) types
could be used.
figure(coroutines/awaitable)
(awaitable)
(AwaitableFig)
The tt(Awaiter) type that's eventually used is either an object of
tt(co_await's expr's) type, or it is the return type of the (implicitly called
when defined) coroutine handler's tt(State::await_transform(expr)) member.
Thus, the tt(Awaitable) object is a em(middle-man), that's only used to obtain
an tt(Awaiter) object. The tt(Awaiter) is the real work-horse in the context
of tt(co_await).
hi(operator co_await) tt(Awaitable) classes may define a member
tt(Awaiter Awaitable::operator co_await()), which may also be provided as a
free function (tt(Awaiter operator co_await(Awaitable &&))). If such a
tt(co_await) conversion operator is available then it is used to obtain the
tt(Awaiter) object from the tt(Awaitable) object. If such a conversion
operator is em(not) available then the tt(Awaitable) object em(is) the
tt(Awaiter) object.
As an aside: the types tt(Awaitable) and tt(Awaiter) are used here as formal
class names, and in actual programs the software engineer is free to use other
(maybe more descriptive) names.
|