Topic: current stackless coroutines proposal
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Tue, 6 Mar 2018 14:02:02 -0800 (PST)
Raw View
------=_Part_13375_1085241841.1520373722606
Content-Type: multipart/alternative;
boundary="----=_Part_13376_1665717800.1520373722606"
------=_Part_13376_1665717800.1520373722606
Content-Type: text/plain; charset="UTF-8"
Hi,
We all know about stackless coroutines proposal Gor Nishanov is working on
right now -- there is a good chance it is going to land in C++20.
It is essentially a composition of various tools that causes compiler to
generate a C++ object (a state machine) that optionally allows caller
coroutine to "subscribe" to a "ready" event (via co_await). All of this is
hidden behind plain function declaration. And to make it efficient a few
compiler optimizations are available (if coroutine body is visible) -- heap
elision, etc.
More info can be found in discussion here:
https://github.com/lewissbaker/lewissbaker.github.io/issues/1#issuecomment-367910971
I find that approach taken isn't ideal:
- if for optimizations we need body to be visible -- what is the benefit of
hiding coroutine behind "plain function" facade?
- all this transformations lead to creation of a plain C++ object --
instead of inventing new semantics of interacting with coroutine why don't
we simply expose that object interface to end user?
- having to propagate 'co_await's down the call tree doesn't seem ideal
- for coroutines that can be located on stack you have to rely on compiler
to notice that
- and etc
So instead of hiding coroutine behind 'plain function' interface and
teaching compiler how to work around its limitations -- why don't we use
approach similar to one used by templates? They do the similar thing --
generate C++ entities (functions and objects) from template code... Like
this:
coroutine int mycoro(int a, char* b) { ... } // has to be defined in
declaration
int main()
{
for(auto x: mc(1,"abc")) ... ; // we explicitly allocate coroutine
on stack
}
In this way:
- each client "sees" entire coroutine and knows how big is it's frame
- you explicitly control coroutine frame allocation
- no need for new compiler optimizations -- in fact, only portion of
compiler that performs template translation needs to be changed
- generated object can be very similar to one in current proposal -- main
difference is how coroutine is represented in the code
- resulting object will have resume() method (to switch machine to next
state) and on_ready(ready_cb) (to enable "awaiting", visible only from
other coroutine)
- note that "awaitable" coroutine is the one that isn't always "ready"
after each "resume()" call -- can be auto-detected by compiler, or
specified explicitly
- since coroutine clearly differs from function -- no need for a keyword
when one coroutine calls another
What do you think about this approach?
Regards,
Michael.
P.S. Note that coroutine generation doesn't even require any changes to the
language -- it can theoretically be done by some sort of tool that takes
coroutine code and builds a state machine C++ class, that later can be
compiled with C++ compiler and used by your code.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f33c743d-b85a-4160-8b8d-b51e3a958ed9%40isocpp.org.
------=_Part_13376_1665717800.1520373722606
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi,<div><br></div><div>We all know about stackless corouti=
nes proposal Gor Nishanov is working on right now -- there is a good chance=
it is going to land in C++20.</div><div><br></div><div>It is essentially a=
composition of various tools that causes compiler to generate a C++ object=
(a state machine) that optionally allows caller coroutine to "subscri=
be" to a "ready" event (via co_await). All of this is hidden=
behind plain function declaration. And to make it efficient a few compiler=
optimizations are available (if coroutine body is visible) -- heap elision=
, etc.</div><div><br></div><div>More info can be found in discussion here:<=
/div><div>https://github.com/lewissbaker/lewissbaker.github.io/issues/1#iss=
uecomment-367910971<br></div><div><br></div><div>I find that approach taken=
isn't ideal:</div><div>- if for optimizations we need body to be visib=
le -- what is the benefit of hiding coroutine behind "plain function&q=
uot; facade?</div><div>- all this transformations lead to creation of a pla=
in C++ object -- instead of inventing new semantics of interacting with cor=
outine why don't we simply expose that object interface to end user?</d=
iv><div>- having to propagate 'co_await's down the call tree doesn&=
#39;t seem ideal</div><div>- for coroutines that can be located on stack yo=
u have to rely on compiler to notice that</div><div>- and etc</div><div><br=
></div><div>So instead of hiding coroutine behind 'plain function' =
interface and teaching compiler how to work around its limitations -- why d=
on't we use approach similar to one used by templates? They do the simi=
lar thing -- generate C++ entities (functions and objects) from template co=
de... Like this:<br></div><div><br></div><div>coroutine int mycoro(int a, c=
har* b) { ... }=C2=A0 // has to be defined in declaration</div><div><br></d=
iv><div>int main()</div><div>{</div><div>=C2=A0 =C2=A0 for(auto x: mc(1,&qu=
ot;abc")) ... ;=C2=A0 =C2=A0 // we explicitly allocate coroutine on st=
ack<br></div><div>}<br></div><br><div>In this way:</div><div>- each client =
"sees" entire coroutine and knows how big is it's frame</div>=
<div>- you explicitly control coroutine frame allocation</div><div>- no nee=
d for new compiler optimizations -- in fact, only portion of compiler that =
performs template translation needs to be changed</div><div>- generated obj=
ect can be very similar to one in current proposal -- main difference is ho=
w coroutine is represented in the code</div><div>=C2=A0 =C2=A0 - resulting =
object will have resume() method (to switch machine to next state) and on_r=
eady(ready_cb) (to enable "awaiting", visible only from other cor=
outine)</div><div>=C2=A0 =C2=A0 - note that "awaitable" coroutine=
is the one that isn't always "ready" after each "resume=
()" call -- can be auto-detected by compiler, or specified explicitly<=
/div><div>- since coroutine clearly differs from function -- no need for a =
keyword when one coroutine calls another</div><div><br></div><div>What do y=
ou think about this approach?</div><div><br></div><div>Regards,</div><div>M=
ichael.</div><div><br></div><div><br></div><div>P.S. Note that coroutine ge=
neration doesn't even require any changes to the language -- it can the=
oretically be done by some sort of tool that takes coroutine code and build=
s a state machine C++ class, that later can be compiled with C++ compiler a=
nd used by your code.</div><div><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/f33c743d-b85a-4160-8b8d-b51e3a958ed9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f33c743d-b85a-4160-8b8d-b51e3a958ed9=
%40isocpp.org</a>.<br />
------=_Part_13376_1665717800.1520373722606--
------=_Part_13375_1085241841.1520373722606--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Tue, 6 Mar 2018 21:33:14 -0800 (PST)
Raw View
------=_Part_19360_1476682865.1520400794977
Content-Type: multipart/alternative;
boundary="----=_Part_19361_2036909410.1520400794978"
------=_Part_19361_2036909410.1520400794978
Content-Type: text/plain; charset="UTF-8"
On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:
>
> Hi,
>
> We all know about stackless coroutines proposal Gor Nishanov is working on
> right now -- there is a good chance it is going to land in C++20.
>
> It is essentially a composition of various tools that causes compiler to
> generate a C++ object (a state machine) that optionally allows caller
> coroutine to "subscribe" to a "ready" event (via co_await). All of this is
> hidden behind plain function declaration. And to make it efficient a few
> compiler optimizations are available (if coroutine body is visible) -- heap
> elision, etc.
>
> More info can be found in discussion here:
>
> https://github.com/lewissbaker/lewissbaker.github.io/issues/1#issuecomment-367910971
>
> I find that approach taken isn't ideal:
> - if for optimizations we need body to be visible -- what is the benefit
> of hiding coroutine behind "plain function" facade?
>
Which optimizations are we talking about? Does everyone who wants to use
coroutines want those optimizations? At all times? If not, why force them
on those who just want easily written async code?
- all this transformations lead to creation of a plain C++ object --
> instead of inventing new semantics of interacting with coroutine why don't
> we simply expose that object interface to end user?
>
Because the whole point of the Coroutines TS proposal is to make
asynchronous code look almost identical to synchronous code. There have
been many discussions of alternative coroutine systems, and while I prefer
many designs on the basis of better functionality, not one of these
alternatives can offer the interface simplicity from an end-user
perspective as the Coroutines TS.
Oh yes, *writing* an awaitable type is a nightmarish netherworld of pain,
suffering, and subtle bugs. But *using* such a type is quick and easy.
> - having to propagate 'co_await's down the call tree doesn't seem ideal
>
Yes, as has been noted by many others.
- for coroutines that can be located on stack you have to rely on compiler
> to notice that
>
Yes, again, we know that. We knew that years ago.
- and etc
>
> So instead of hiding coroutine behind 'plain function' interface and
> teaching compiler how to work around its limitations -- why don't we use
> approach similar to one used by templates? They do the similar thing --
> generate C++ entities (functions and objects) from template code... Like
> this:
>
> coroutine int mycoro(int a, char* b) { ... } // has to be defined in
> declaration
>
> int main()
> {
> for(auto x: mc(1,"abc")) ... ; // we explicitly allocate coroutine
> on stack
> }
>
P0939 <http://wg21.link/P0939>makes it clear that the committee is adamant
about getting the Coroutines TS in C++20 with its current design, and
similarly makes it clear that 11th hour redesigns aren't going to be
allowed to completely derail existing proposals that have had years of
prior design. As such, any discussion in this direction is entirely
academic.
Your design appears to be similar to the various "resumable functions"
proposals: P0114 <http://wg21.link/P0114>and so forth. They look great for
generators, but they require a lot more effort to write genuine
asynchronous function calls. Or at least, not without effort on the part of
the caller.
Remember: the "Coroutines TS" is really the "Continuations TS": it's all
about halting a function's execution and using the result of an expression
to schedule the continuation of that function's execution (and unpacking
the result of the expression when the function is resumed). At its core,
it's all about putting `.then` in the language. This usage pattern is the
Coroutines TS system working at its best. So if you want to challenge it,
you need to find a design that can accomplish what it does *better* than it
currently does.
Your design handles generators well. But generators have never been a
serious aspect of the Coroutines TS design. Oh sure, it can handle
generators to some degree, but it's not very good at them due to the lack
of call stack preservation of more than itself. It's exceedingly terrible
at mixing generators and so forth.
But you're not going to stop the Coroutines TS from becoming part of the
standard by presenting a solution that only solves a minor part of the
problem the TS is intended to solve.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/44752d04-24c2-4f5f-b95d-41d2ab9f1e7e%40isocpp.org.
------=_Part_19361_2036909410.1520400794978
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Mic=
hael Kilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D=
"ltr">Hi,<div><br></div><div>We all know about stackless coroutines proposa=
l Gor Nishanov is working on right now -- there is a good chance it is goin=
g to land in C++20.</div><div><br></div><div>It is essentially a compositio=
n of various tools that causes compiler to generate a C++ object (a state m=
achine) that optionally allows caller coroutine to "subscribe" to=
a "ready" event (via co_await). All of this is hidden behind pla=
in function declaration. And to make it efficient a few compiler optimizati=
ons are available (if coroutine body is visible) -- heap elision, etc.</div=
><div><br></div><div>More info can be found in discussion here:</div><div><=
a href=3D"https://github.com/lewissbaker/lewissbaker.github.io/issues/1#iss=
uecomment-367910971" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Flew=
issbaker%2Flewissbaker.github.io%2Fissues%2F1%23issuecomment-367910971\x26s=
a\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFHHjQjKze-IE5A7nJjgU3zFjF1hA';retur=
n true;" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%=
3A%2F%2Fgithub.com%2Flewissbaker%2Flewissbaker.github.io%2Fissues%2F1%23iss=
uecomment-367910971\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFHHjQjKze-IE5A7=
nJjgU3zFjF1hA';return true;">https://github.com/<wbr>lewissbaker/lewiss=
baker.<wbr>github.io/issues/1#<wbr>issuecomment-367910971</a><br></div><div=
><br></div><div>I find that approach taken isn't ideal:</div><div>- if =
for optimizations we need body to be visible -- what is the benefit of hidi=
ng coroutine behind "plain function" facade?</div></div></blockqu=
ote><div><br>Which optimizations are we talking about? Does everyone who wa=
nts to use coroutines want those optimizations? At all times? If not, why f=
orce them on those who just want easily written async code?<br><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>- all this=
transformations lead to creation of a plain C++ object -- instead of inven=
ting new semantics of interacting with coroutine why don't we simply ex=
pose that object interface to end user?</div></div></blockquote><div><br>Be=
cause the whole point of the Coroutines TS proposal is to make asynchronous=
code look almost identical to synchronous code. There have been many discu=
ssions of alternative coroutine systems, and while I prefer many designs on=
the basis of better functionality, not one of these alternatives can offer=
the interface simplicity from an end-user perspective as the Coroutines TS=
..<br><br>Oh yes, <i>writing</i> an awaitable type is a nightmarish netherwo=
rld of pain, suffering, and subtle bugs. But <i>using</i> such a type is qu=
ick and easy.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div>- having to propagate 'co_await's down the cal=
l tree doesn't seem ideal</div></div></blockquote><div><br>Yes, as has =
been noted by many others.<br><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div>- for coroutines that can be located on sta=
ck you have to rely on compiler to notice that</div></div></blockquote><div=
><br>Yes, again, we know that. We knew that years ago.<br><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>- and etc</div>=
<div><br></div><div>So instead of hiding coroutine behind 'plain functi=
on' interface and teaching compiler how to work around its limitations =
-- why don't we use approach similar to one used by templates? They do =
the similar thing -- generate C++ entities (functions and objects) from tem=
plate code... Like this:<br></div><div><br></div><div>coroutine int mycoro(=
int a, char* b) { ... }=C2=A0 // has to be defined in declaration</div><div=
><br></div><div>int main()</div><div>{</div><div>=C2=A0 =C2=A0 for(auto x: =
mc(1,"abc")) ... ;=C2=A0 =C2=A0 // we explicitly allocate corouti=
ne on stack<br></div><div>}<br></div></div></blockquote><div><br><a href=3D=
"http://wg21.link/P0939">P0939 </a>makes it clear that the committee is ada=
mant about getting the Coroutines TS in C++20 with its current design, and =
similarly makes it clear that 11th hour redesigns aren't going to be al=
lowed to completely derail existing proposals that have had years of prior =
design. As such, any discussion in this direction is entirely academic.<br>=
<br>Your design appears to be similar to the various "resumable functi=
ons" proposals: <a href=3D"http://wg21.link/P0114">P0114 </a>and so fo=
rth. They look great for generators, but they require a lot more effort to =
write genuine asynchronous function calls. Or at least, not without effort =
on the part of the caller.<br><br>Remember: the "Coroutines TS" i=
s really the "Continuations TS": it's all about halting a fun=
ction's execution and using the result of an expression to schedule the=
continuation of that function's execution (and unpacking the result of=
the expression when the function is resumed). At its core, it's all ab=
out putting `.then` in the language. This usage pattern is the Coroutines T=
S system working at its best. So if you want to challenge it, you need to f=
ind a design that can accomplish what it does <i>better</i> than it current=
ly does.<br><br>Your design handles generators well. But generators have ne=
ver been a serious aspect of the Coroutines TS design. Oh sure, it can hand=
le generators to some degree, but it's not very good at them due to the=
lack of call stack preservation of more than itself. It's exceedingly =
terrible at mixing generators and so forth.<br><br>But you're not going=
to stop the Coroutines TS from becoming part of the standard by presenting=
a solution that only solves a minor part of the problem the TS is intended=
to solve.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/44752d04-24c2-4f5f-b95d-41d2ab9f1e7e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/44752d04-24c2-4f5f-b95d-41d2ab9f1e7e=
%40isocpp.org</a>.<br />
------=_Part_19361_2036909410.1520400794978--
------=_Part_19360_1476682865.1520400794977--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Wed, 7 Mar 2018 00:29:26 -0600
Raw View
--94eb2c070e724e4f160566ccaea7
Content-Type: text/plain; charset="UTF-8"
On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:
>>
>> But you're not going to stop the Coroutines TS from becoming part of the
>> standard by presenting a solution that only solves a minor part of the
>> problem the TS is intended to solve.
>>
>
Damn it! My evil plans got foiled again!
Well, all I wanted to hear is opinions on given approach -- because
fundamentally it changes very little in current proposal. Only instead of
hiding behind opaque "just a function" facade this coroutine hides behind
transparent "template" facade. The way I see it -- it makes implementation
(on compiler side) easier. Was this approach ever considered? If yes -- why
it was rejected?
> Which optimizations are we talking about?
There is a talk given by Gor about "disappearing coroutines" where
(assuming compiler has required optimizations) coroutine gets completely
"inlined". He mentioned "heap allocation elision" optimization there --
whih to me looks like a big mistake (just like copy elision was).
> They look great for generators, but they require a lot more effort to
write genuine asynchronous function calls.
No, not really... At least I don't see it.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6ws_Lb7vatD05bb_G5wjxo%3D%2BS-h%2BinLFbF6enCrkMgzQ%40mail.gmail.com.
--94eb2c070e724e4f160566ccaea7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
ue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=
=3D"">On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">But you're not=
going to stop the Coroutines TS from becoming part of the standard by pres=
enting a solution that only solves a minor part of the problem the TS is in=
tended to solve.<br></div></blockquote></span></div></blockquote><div><br><=
/div><div>Damn it! My evil plans got foiled again!</div><div><br></div><div=
>Well, all I wanted to hear is opinions on given approach -- because fundam=
entally it changes very little in current proposal. Only instead of hiding =
behind opaque "just a function" facade this coroutine hides behin=
d transparent "template" facade. The way I see it -- it makes imp=
lementation (on compiler side) easier. Was this approach ever considered? I=
f yes -- why it was rejected?</div><div><br></div><div><br></div><div>>=
=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:nor=
mal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;=
text-transform:none;white-space:normal;word-spacing:0px;background-color:rg=
b(255,255,255);text-decoration-style:initial;text-decoration-color:initial;=
float:none;display:inline">Which optimizations are we talking about?</span>
</div><div><br></div><div>There is a talk given by Gor about "disappea=
ring coroutines" where (assuming compiler has required optimizations) =
coroutine gets completely "inlined". He mentioned "heap allo=
cation elision" optimization there -- whih to me looks like a big mist=
ake (just like copy elision was).</div><div><br></div><div><br></div><div>&=
gt;=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:nor=
mal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;=
text-transform:none;white-space:normal;word-spacing:0px;background-color:rg=
b(255,255,255);text-decoration-style:initial;text-decoration-color:initial;=
float:none;display:inline">They look great for generators, but they require=
a lot more effort to write genuine asynchronous function calls.</span>
</div><div><br></div><div>No, not really... At least I don't see it.</d=
iv><div><br></div></div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6ws_Lb7vatD05bb_G5wjxo%3D%2B=
S-h%2BinLFbF6enCrkMgzQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP=
6ws_Lb7vatD05bb_G5wjxo%3D%2BS-h%2BinLFbF6enCrkMgzQ%40mail.gmail.com</a>.<br=
/>
--94eb2c070e724e4f160566ccaea7--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 7 Mar 2018 10:08:05 +0200
Raw View
On 7 March 2018 at 07:33, Nicol Bolas <jmckesson@gmail.com> wrote:
> P0939 makes it clear that the committee is adamant about getting the
> Coroutines TS in C++20 with its current design, and similarly makes it clear
The authors of P0939 are not the committee, they don't speak for the committee,
and they don't make decisions for the committee. It's a recommendation.
> that 11th hour redesigns aren't going to be allowed to completely derail
> existing proposals that have had years of prior design. As such, any
> discussion in this direction is entirely academic.
That remains to be seen, because such discussions are going to happen, in the
committee.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUY5i0ypq%3DskWR6aX36WEeM02aqYwChd40E2y3nX-zxfhA%40mail.gmail.com.
.
Author: Todd Fleming <tbfleming@gmail.com>
Date: Wed, 7 Mar 2018 06:29:21 -0800 (PST)
Raw View
------=_Part_20267_706643710.1520432961845
Content-Type: multipart/alternative;
boundary="----=_Part_20268_289013401.1520432961845"
------=_Part_20268_289013401.1520432961845
Content-Type: text/plain; charset="UTF-8"
On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:
>
> There is a talk given by Gor about "disappearing coroutines" where
> (assuming compiler has required optimizations) coroutine gets completely
> "inlined". He mentioned "heap allocation elision" optimization there --
> whih to me looks like a big mistake (just like copy elision was).
>
>
Heap elision has been around for quite a while in clang, long before
coroutines. What's the big mistake with heap elision and copy elision? My
code has benefited from both.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/68f47072-1968-4597-8ebc-774b16e3cc12%40isocpp.org.
------=_Part_20268_289013401.1520432961845
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael K=
ilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div>There is a talk given by Gor about &qu=
ot;disappearing coroutines" where (assuming compiler has required opti=
mizations) coroutine gets completely "inlined". He mentioned &quo=
t;heap allocation elision" optimization there -- whih to me looks like=
a big mistake (just like copy elision was).</div><div><br></div></div></di=
v></div></blockquote><div><br></div><div>Heap elision has been around for q=
uite a while in clang, long before coroutines. What's the big mistake w=
ith heap elision and copy elision? My code has benefited from both.</div><d=
iv><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/68f47072-1968-4597-8ebc-774b16e3cc12%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/68f47072-1968-4597-8ebc-774b16e3cc12=
%40isocpp.org</a>.<br />
------=_Part_20268_289013401.1520432961845--
------=_Part_20267_706643710.1520432961845--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 7 Mar 2018 06:51:20 -0800 (PST)
Raw View
------=_Part_20832_1865453755.1520434280446
Content-Type: multipart/alternative;
boundary="----=_Part_20833_70264117.1520434280446"
------=_Part_20833_70264117.1520434280446
Content-Type: text/plain; charset="UTF-8"
On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:
>
> On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:
>>>
>>> But you're not going to stop the Coroutines TS from becoming part of the
>>> standard by presenting a solution that only solves a minor part of the
>>> problem the TS is intended to solve.
>>>
>>
> Damn it! My evil plans got foiled again!
>
> Well, all I wanted to hear is opinions on given approach -- because
> fundamentally it changes very little in current proposal. Only instead of
> hiding behind opaque "just a function" facade this coroutine hides behind
> transparent "template" facade. The way I see it -- it makes implementation
> (on compiler side) easier. Was this approach ever considered? If yes -- why
> it was rejected?
>
Resumable function-style coroutines weren't "rejected", as I understand it.
They just stopped running the race. The people proposing it never
implemented it, while Gor took the time and effort to get a decent
implementation into a shipping compiler for people to use. Gor iterated
heavily on the proposal, while the others never really improved or changed.
Coroutines TS has won essentially by default; the people behind it put in
the work to prove that the idea functions, and its competition didn't.
> Which optimizations are we talking about?
>
> There is a talk given by Gor about "disappearing coroutines" where
> (assuming compiler has required optimizations) coroutine gets completely
> "inlined". He mentioned "heap allocation elision" optimization there --
> whih to me looks like a big mistake (just like copy elision was).
>
Sure, but not every case of coroutines relies on that. Coroutines being
completely inlined is primarily for generator coroutines, which again
aren't exactly the primary use case for the feature.
> They look great for generators, but they require a lot more effort to
> write genuine asynchronous function calls.
>
> No, not really... At least I don't see it.
>
OK, take this synchronous code:
int sync_call(...)
{
auto val = some_function(...);
return val + 1;
}
This is the async version of that, using `co_await`:
std::future<int> async_call(...)
{
auto val = co_await std::async(some_function, ...);
co_return val + 1;
}
Write the equivalent of `async_call` using your coroutines system. Here are
the rules. You must invoke `std::async`. You must use `future::then` to
resume the rest of `async_call`. Your function must return a `future<int>`
(which the caller themselves can use `::then` on). Oh, and don't forget:
the future returned from the `async` call may not be a `future<int>`;
merely some type that can have one added to it, the result of which is
convertible to `int`.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/33409afd-5bf6-40e0-a214-720535f9b54d%40isocpp.org.
------=_Part_20833_70264117.1520434280446
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael K=
ilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote">On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bola=
s <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfus=
cated-mailto=3D"AFGBbUHmAwAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&=
#39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&=
#39;;return true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><span>On Tuesday, March 6, 2018 at 5:02:=
02 PM UTC-5, Michael Kilburn wrote:<blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr">But you're not going to stop the Coroutines TS from b=
ecoming part of the standard by presenting a solution that only solves a mi=
nor part of the problem the TS is intended to solve.<br></div></blockquote>=
</span></div></blockquote><div><br></div><div>Damn it! My evil plans got fo=
iled again!</div><div><br></div><div>Well, all I wanted to hear is opinions=
on given approach -- because fundamentally it changes very little in curre=
nt proposal. Only instead of hiding behind opaque "just a function&quo=
t; facade this coroutine hides behind transparent "template" faca=
de. The way I see it -- it makes implementation (on compiler side) easier. =
Was this approach ever considered? If yes -- why it was rejected?</div></di=
v></div></div></blockquote><div><br>Resumable function-style coroutines wer=
en't "rejected", as I understand it. They just stopped runnin=
g the race. The people proposing it never implemented it, while Gor took th=
e time and effort to get a decent implementation into a shipping compiler f=
or people to use. Gor iterated heavily on the proposal, while the others ne=
ver really improved or changed.<br><br>Coroutines TS has won essentially by=
default; the people behind it put in the work to prove that the idea funct=
ions, and its competition didn't.<br><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=
</div><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">Which optimiz=
ations are we talking about?</span>
</div><div><br></div><div>There is a talk given by Gor about "disappea=
ring coroutines" where (assuming compiler has required optimizations) =
coroutine gets completely "inlined". He mentioned "heap allo=
cation elision" optimization there -- whih to me looks like a big mist=
ake (just like copy elision was).</div></div></div></div></blockquote><div>=
<br>Sure, but not every case of coroutines relies on that. Coroutines being=
completely inlined is primarily for generator coroutines, which again aren=
't exactly the primary use case for the feature.<br><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><div></div><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">They look gre=
at for generators, but they require a lot more effort to write genuine asyn=
chronous function calls.</span>
</div><div><br></div><div>No, not really... At least I don't see it.</d=
iv></div></div></div></blockquote><div><br>OK, take this synchronous code:<=
br><br><div style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: br=
eak-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> sync_ca=
ll</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(...)</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> val </span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> some_function</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(...);</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> val </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-pret=
tify">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></co=
de></div><br>This is the async version of that, using `co_await`:<br><br><d=
iv style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 18=
7, 187); border-style: solid; border-width: 1px; overflow-wrap: break-word;=
" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">future</span><span style=
=3D"color: #080;" class=3D"styled-by-prettify"><int></span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> async_call</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(...)</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> val </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> co_await std</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">async</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">some_fu=
nction</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">...);</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 co_return val </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">+</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></div></code></div><br>Write the equivalent=
of `async_call` using your coroutines system. Here are the rules. You must=
invoke `std::async`. You must use `future::then` to resume the rest of `as=
ync_call`. Your function must return a `future<int>` (which the calle=
r themselves can use `::then` on). Oh, and don't forget: the future ret=
urned from the `async` call may not be a `future<int>`; merely some t=
ype that can have one added to it, the result of which is convertible to `i=
nt`.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/33409afd-5bf6-40e0-a214-720535f9b54d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/33409afd-5bf6-40e0-a214-720535f9b54d=
%40isocpp.org</a>.<br />
------=_Part_20833_70264117.1520434280446--
------=_Part_20832_1865453755.1520434280446--
.
Author: Lee Howes <xrikcus@gmail.com>
Date: Wed, 7 Mar 2018 09:17:57 -0800
Raw View
--001a114277329602020566d5bd4a
Content-Type: text/plain; charset="UTF-8"
> Gor iterated heavily on the proposal, while the others never really
improved or changed.
Oliver Kowalke has updated his series of fibers papers:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf so
there is continued work on the stackful coroutines approach, at least in
the sense of the required primitives.
Michael:
On "having to propagate 'co_await's down the call tree doesn't seem ideal"
for many of us this is absolutely ideal, it's so ideal that we've
experimented with enforcing it even in fiber-based code that doesn't need
it and this feature is one reason that may cause us to port some of our
fiber-based code to these coroutines! The safety benefits of doing that
are enormous in terms of enforcement of asynchronous interfaces,
guaranteeing where code runs under complete control of caller and callee
library constructs, and ensuring that different libraries do not interfere
with each others' synchronisation primitives. We've actively been
*removing* continuation support from futures in some parts of our codebase
for similar reasons - explicitness has enormous value. A few weeks of extra
work strengthening a library to make it trivial to use by a caller, while
maintaining all the safety my library needs, is well worth the effort.
We clearly need to be able to co_await on opaque library calls - so there
are going to be cases all over the codebase where the compiler can not, and
indeed should not, have any visibility into the library code. We even want
coroutines to sit behind dynamic dispatch - is there any reason why a
virtual function should not be a coroutine? Enforcing visibility to the
compiler would break that. Those are cases where we will not get automatic
heap elision. We may want explicit stack allocation instead and this can be
implemented on top of the current TS, though some modifications would make
it cleaner. We may not care because the odd heap allocation across
asynchronous library interfaces is trivial, and we have worse than that now
with synchronising promise/future pairs.
A lot of work has gone into this, and while it is not perfect and there are
certainly concerns from some parties with rushing it into the standard, on
balance long years of discussions around similar questions to those you are
asking have got us to this point.
On 7 March 2018 at 06:51, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:
>>
>> On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:
>>>>
>>>> But you're not going to stop the Coroutines TS from becoming part of
>>>> the standard by presenting a solution that only solves a minor part of the
>>>> problem the TS is intended to solve.
>>>>
>>>
>> Damn it! My evil plans got foiled again!
>>
>> Well, all I wanted to hear is opinions on given approach -- because
>> fundamentally it changes very little in current proposal. Only instead of
>> hiding behind opaque "just a function" facade this coroutine hides behind
>> transparent "template" facade. The way I see it -- it makes implementation
>> (on compiler side) easier. Was this approach ever considered? If yes -- why
>> it was rejected?
>>
>
> Resumable function-style coroutines weren't "rejected", as I understand
> it. They just stopped running the race. The people proposing it never
> implemented it, while Gor took the time and effort to get a decent
> implementation into a shipping compiler for people to use. Gor iterated
> heavily on the proposal, while the others never really improved or changed.
>
> Coroutines TS has won essentially by default; the people behind it put in
> the work to prove that the idea functions, and its competition didn't.
>
> > Which optimizations are we talking about?
>>
>> There is a talk given by Gor about "disappearing coroutines" where
>> (assuming compiler has required optimizations) coroutine gets completely
>> "inlined". He mentioned "heap allocation elision" optimization there --
>> whih to me looks like a big mistake (just like copy elision was).
>>
>
> Sure, but not every case of coroutines relies on that. Coroutines being
> completely inlined is primarily for generator coroutines, which again
> aren't exactly the primary use case for the feature.
>
> > They look great for generators, but they require a lot more effort to
>> write genuine asynchronous function calls.
>>
>> No, not really... At least I don't see it.
>>
>
> OK, take this synchronous code:
>
> int sync_call(...)
> {
> auto val = some_function(...);
> return val + 1;
> }
>
> This is the async version of that, using `co_await`:
>
> std::future<int> async_call(...)
> {
> auto val = co_await std::async(some_function, ...);
> co_return val + 1;
> }
>
> Write the equivalent of `async_call` using your coroutines system. Here
> are the rules. You must invoke `std::async`. You must use `future::then` to
> resume the rest of `async_call`. Your function must return a `future<int>`
> (which the caller themselves can use `::then` on). Oh, and don't forget:
> the future returned from the `async` call may not be a `future<int>`;
> merely some type that can have one added to it, the result of which is
> convertible to `int`.
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/33409afd-5bf6-40e0-
> a214-720535f9b54d%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/33409afd-5bf6-40e0-a214-720535f9b54d%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNXqrHMd2E67uBJqpnGbe%3D3kxFjx2Q6Buwsj%3D9Aj23Prkg%40mail.gmail.com.
--001a114277329602020566d5bd4a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>>=C2=A0<span style=3D"color:rgb(34,34,34);font-fam=
ily:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatu=
res:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;t=
ext-align:start;text-indent:0px;text-transform:none;white-space:normal;word=
-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initia=
l;text-decoration-color:initial;float:none;display:inline">Gor iterated hea=
vily on the proposal, while the others never really improved or changed.</s=
pan></div><div><span style=3D"font-size:12.8px">=C2=A0</span><br></div>Oliv=
er Kowalke has updated his series of fibers papers:=C2=A0<a href=3D"http://=
www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf">http://www.op=
en-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf</a> so there is cont=
inued work on the stackful coroutines approach, at least in the sense of th=
e required primitives.<div><br><div><div><br></div><div>Michael:</div><div>=
On "<span style=3D"color:rgb(80,0,80);font-size:12.8px">having to prop=
agate 'co_await's down the call tree doesn't seem ideal" f=
or many of us this is absolutely ideal, it's so ideal that we've ex=
perimented with enforcing it even in fiber-based code that doesn't need=
it and this feature is one reason that may cause us to port some of our fi=
ber-based code to these coroutines!=C2=A0 The safety benefits of doing that=
are enormous in terms of enforcement of asynchronous interfaces, guarantee=
ing where code runs under complete control of caller and callee library con=
structs, and ensuring that different libraries do not interfere with each o=
thers' synchronisation primitives. We've actively been *removing* c=
ontinuation support from futures in some parts of our codebase for similar =
reasons - explicitness has enormous value. A few weeks of extra work streng=
thening a library to make it trivial to use by a caller, while maintaining =
all the safety my library needs, is well worth the effort.</span><br></div>=
<div><font color=3D"#500050"><span style=3D"font-size:12.8px"><br></span></=
font></div><div><font color=3D"#500050"><span style=3D"font-size:12.8px">We=
clearly need to be able to co_await on opaque library calls - so there are=
going to be cases all over the codebase where the compiler can not, and in=
deed should not, have any visibility into the library code. We even want co=
routines to sit behind dynamic dispatch - is there any reason why a virtual=
function should not be a coroutine? Enforcing visibility to the compiler w=
ould break that. Those are cases where we will not get automatic heap elisi=
on. We may want explicit stack allocation instead and this can be implement=
ed on top of the current TS, though some modifications would make it cleane=
r. We may not care because the odd heap allocation across asynchronous libr=
ary interfaces is trivial, and we have worse than that now with synchronisi=
ng promise/future pairs.=C2=A0</span></font></div><div><div><br></div><div>=
A lot of work has gone into this, and while it is not perfect and there are=
certainly concerns from some parties with rushing it into the standard, on=
balance long years of discussions around similar questions to those you ar=
e asking have got us to this point.</div><div><br></div></div></div></div><=
/div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On 7 March 2=
018 at 06:51, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmckesson=
@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> wrote:<br>=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">On Wednesd=
ay, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:</span><span c=
lass=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0=
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><di=
v class=3D"gmail_quote">On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <span =
dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span>On Tuesday, March=
6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr">But you're not going to stop the Coro=
utines TS from becoming part of the standard by presenting a solution that =
only solves a minor part of the problem the TS is intended to solve.<br></d=
iv></blockquote></span></div></blockquote><div><br></div><div>Damn it! My e=
vil plans got foiled again!</div><div><br></div><div>Well, all I wanted to =
hear is opinions on given approach -- because fundamentally it changes very=
little in current proposal. Only instead of hiding behind opaque "jus=
t a function" facade this coroutine hides behind transparent "tem=
plate" facade. The way I see it -- it makes implementation (on compile=
r side) easier. Was this approach ever considered? If yes -- why it was rej=
ected?</div></div></div></div></blockquote></span><div><br>Resumable functi=
on-style coroutines weren't "rejected", as I understand it. T=
hey just stopped running the race. The people proposing it never implemente=
d it, while Gor took the time and effort to get a decent implementation int=
o a shipping compiler for people to use. Gor iterated heavily on the propos=
al, while the others never really improved or changed.<br><br>Coroutines TS=
has won essentially by default; the people behind it put in the work to pr=
ove that the idea functions, and its competition didn't.<br><br></div><=
span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-=
left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><d=
iv><div class=3D"gmail_quote"><div></div><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">Which optimiz=
ations are we talking about?</span>
</div><div><br></div><div>There is a talk given by Gor about "disappea=
ring coroutines" where (assuming compiler has required optimizations) =
coroutine gets completely "inlined". He mentioned "heap allo=
cation elision" optimization there -- whih to me looks like a big mist=
ake (just like copy elision was).</div></div></div></div></blockquote></spa=
n><div><br>Sure, but not every case of coroutines relies on that. Coroutine=
s being completely inlined is primarily for generator coroutines, which aga=
in aren't exactly the primary use case for the feature.<br><br></div><s=
pan class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v><div class=3D"gmail_quote"><div></div><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">They look gre=
at for generators, but they require a lot more effort to write genuine asyn=
chronous function calls.</span>
</div><div><br></div><div>No, not really... At least I don't see it.</d=
iv></div></div></div></blockquote></span><div><br>OK, take this synchronous=
code:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px" class=3D"m_-503446360=
6837718252prettyprint"><code class=3D"m_-5034463606837718252prettyprint"><d=
iv class=3D"m_-5034463606837718252subprettyprint"><span style=3D"color:#008=
" class=3D"m_-5034463606837718252styled-by-prettify">int</span><span style=
=3D"color:#000" class=3D"m_-5034463606837718252styled-by-prettify"> sync_ca=
ll</span><span style=3D"color:#660" class=3D"m_-5034463606837718252styled-b=
y-prettify">(...)</span><span style=3D"color:#000" class=3D"m_-503446360683=
7718252styled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m=
_-5034463606837718252styled-by-prettify">{</span><span style=3D"color:#000"=
class=3D"m_-5034463606837718252styled-by-prettify"><br>=C2=A0 </span><span=
style=3D"color:#008" class=3D"m_-5034463606837718252styled-by-prettify">au=
to</span><span style=3D"color:#000" class=3D"m_-5034463606837718252styled-b=
y-prettify"> val </span><span style=3D"color:#660" class=3D"m_-503446360683=
7718252styled-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_=
-5034463606837718252styled-by-prettify"> some_function</span><span style=3D=
"color:#660" class=3D"m_-5034463606837718252styled-by-prettify">(...);</spa=
n><span style=3D"color:#000" class=3D"m_-5034463606837718252styled-by-prett=
ify"><br>=C2=A0 </span><span style=3D"color:#008" class=3D"m_-5034463606837=
718252styled-by-prettify">return</span><span style=3D"color:#000" class=3D"=
m_-5034463606837718252styled-by-prettify"> val </span><span style=3D"color:=
#660" class=3D"m_-5034463606837718252styled-by-prettify">+</span><span styl=
e=3D"color:#000" class=3D"m_-5034463606837718252styled-by-prettify"> </span=
><span style=3D"color:#066" class=3D"m_-5034463606837718252styled-by-pretti=
fy">1</span><span style=3D"color:#660" class=3D"m_-5034463606837718252style=
d-by-prettify">;</span><span style=3D"color:#000" class=3D"m_-5034463606837=
718252styled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_=
-5034463606837718252styled-by-prettify">}</span></div></code></div><br>This=
is the async version of that, using `co_await`:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px" class=3D"m_-5034463606837718252prettyprint"><code clas=
s=3D"m_-5034463606837718252prettyprint"><div class=3D"m_-503446360683771825=
2subprettyprint"><span style=3D"color:#000" class=3D"m_-5034463606837718252=
styled-by-prettify">std</span><span style=3D"color:#660" class=3D"m_-503446=
3606837718252styled-by-prettify">::</span><span style=3D"color:#000" class=
=3D"m_-5034463606837718252styled-by-prettify">future</span><span style=3D"c=
olor:#080" class=3D"m_-5034463606837718252styled-by-prettify"><int></=
span><span style=3D"color:#000" class=3D"m_-5034463606837718252styled-by-pr=
ettify"> async_call</span><span style=3D"color:#660" class=3D"m_-5034463606=
837718252styled-by-prettify">(...)</span><span style=3D"color:#000" class=
=3D"m_-5034463606837718252styled-by-prettify"><br></span><span style=3D"col=
or:#660" class=3D"m_-5034463606837718252styled-by-prettify">{</span><span s=
tyle=3D"color:#000" class=3D"m_-5034463606837718252styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color:#008" class=3D"m_-5034463606837718252sty=
led-by-prettify">auto</span><span style=3D"color:#000" class=3D"m_-50344636=
06837718252styled-by-prettify"> val </span><span style=3D"color:#660" class=
=3D"m_-5034463606837718252styled-by-prettify">=3D</span><span style=3D"colo=
r:#000" class=3D"m_-5034463606837718252styled-by-prettify"> co_await std</s=
pan><span style=3D"color:#660" class=3D"m_-5034463606837718252styled-by-pre=
ttify">::</span><span style=3D"color:#000" class=3D"m_-5034463606837718252s=
tyled-by-prettify">async</span><span style=3D"color:#660" class=3D"m_-50344=
63606837718252styled-by-prettify">(</span><span style=3D"color:#000" class=
=3D"m_-5034463606837718252styled-by-prettify">some_function</span><span sty=
le=3D"color:#660" class=3D"m_-5034463606837718252styled-by-prettify">,</spa=
n><span style=3D"color:#000" class=3D"m_-5034463606837718252styled-by-prett=
ify"> </span><span style=3D"color:#660" class=3D"m_-5034463606837718252styl=
ed-by-prettify">...);</span><span style=3D"color:#000" class=3D"m_-50344636=
06837718252styled-by-prettify"><br>=C2=A0 co_return val </span><span style=
=3D"color:#660" class=3D"m_-5034463606837718252styled-by-prettify">+</span>=
<span style=3D"color:#000" class=3D"m_-5034463606837718252styled-by-prettif=
y"> </span><span style=3D"color:#066" class=3D"m_-5034463606837718252styled=
-by-prettify">1</span><span style=3D"color:#660" class=3D"m_-50344636068377=
18252styled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_-503=
4463606837718252styled-by-prettify"><br></span><span style=3D"color:#660" c=
lass=3D"m_-5034463606837718252styled-by-prettify">}</span></div></code></di=
v><br>Write the equivalent of `async_call` using your coroutines system. He=
re are the rules. You must invoke `std::async`. You must use `future::then`=
to resume the rest of `async_call`. Your function must return a `future<=
;int>` (which the caller themselves can use `::then` on). Oh, and don=
9;t forget: the future returned from the `async` call may not be a `future&=
lt;int>`; merely some type that can have one added to it, the result of =
which is convertible to `int`.<br></div></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/33409afd-5bf6-40e0-a214-720535f9b54d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/3340=
9afd-5bf6-40e0-<wbr>a214-720535f9b54d%40isocpp.org</a><wbr>.<br>
</blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAJH_FNXqrHMd2E67uBJqpnGbe%3D3kxFjx2Q=
6Buwsj%3D9Aj23Prkg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNXqrHMd=
2E67uBJqpnGbe%3D3kxFjx2Q6Buwsj%3D9Aj23Prkg%40mail.gmail.com</a>.<br />
--001a114277329602020566d5bd4a--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 7 Mar 2018 13:17:21 -0800 (PST)
Raw View
------=_Part_253_659382323.1520457441549
Content-Type: multipart/alternative;
boundary="----=_Part_254_1301925184.1520457441549"
------=_Part_254_1301925184.1520457441549
Content-Type: text/plain; charset="UTF-8"
On Wednesday, March 7, 2018 at 12:18:01 PM UTC-5, Lee Howes wrote:
>
> > Gor iterated heavily on the proposal, while the others never really
> improved or changed.
>
> Oliver Kowalke has updated his series of fibers papers:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf so
> there is continued work on the stackful coroutines approach, at least in
> the sense of the required primitives.
>
I was talking about the language-based proposals. The library coroutines
proposal has had a number of iterations over the years. Though some of the
changes have been pretty radical.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/9eb810e3-777f-451c-9d60-7093ed99ea5b%40isocpp.org.
------=_Part_254_1301925184.1520457441549
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, March 7, 2018 at 12:18:01 PM UTC-5, Lee Howe=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
>=C2=A0<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;f=
ont-size:12.8px;font-style:normal;font-weight:400;letter-spacing:normal;tex=
t-align:start;text-indent:0px;text-transform:none;white-space:normal;word-s=
pacing:0px;background-color:rgb(255,255,255);float:none;display:inline">Gor=
iterated heavily on the proposal, while the others never really improved o=
r changed.</span></div><div><span style=3D"font-size:12.8px">=C2=A0</span><=
br></div>Oliver Kowalke has updated his series of fibers papers:=C2=A0<a hr=
ef=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf" =
target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://w=
ww.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2=
Fdocs%2Fpapers%2F2018%2Fp0876r0.pdf\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjC=
NGc5tx0aivZcz-nLqYm_OyuwYc1-Q';return true;" onclick=3D"this.href=3D=
9;http://www.google.com/url?q\x3dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc2=
2%2Fwg21%2Fdocs%2Fpapers%2F2018%2Fp0876r0.pdf\x26sa\x3dD\x26sntz\x3d1\x26us=
g\x3dAFQjCNGc5tx0aivZcz-nLqYm_OyuwYc1-Q';return true;">http://www.open-=
std.<wbr>org/jtc1/sc22/wg21/docs/<wbr>papers/2018/p0876r0.pdf</a> so there =
is continued work on the stackful coroutines approach, at least in the sens=
e of the required primitives.</div></blockquote><div><br>I was talking abou=
t the language-based proposals. The library coroutines proposal has had a n=
umber of iterations over the years. Though some of the changes have been pr=
etty radical.</div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/9eb810e3-777f-451c-9d60-7093ed99ea5b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9eb810e3-777f-451c-9d60-7093ed99ea5b=
%40isocpp.org</a>.<br />
------=_Part_254_1301925184.1520457441549--
------=_Part_253_659382323.1520457441549--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Wed, 7 Mar 2018 20:40:04 -0600
Raw View
--94eb2c0e5d9ad584a40566dd97f9
Content-Type: text/plain; charset="UTF-8"
On Wed, Mar 7, 2018 at 8:29 AM, Todd Fleming <tbfleming@gmail.com> wrote:
> On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:
>>
>> There is a talk given by Gor about "disappearing coroutines" where
>> (assuming compiler has required optimizations) coroutine gets completely
>> "inlined". He mentioned "heap allocation elision" optimization there --
>> whih to me looks like a big mistake (just like copy elision was).
>>
>>
> Heap elision has been around for quite a while in clang, long before
> coroutines. What's the big mistake with heap elision and copy elision? My
> code has benefited from both.
>
Copy elision is an illusion, unnecessary complication -- all (decent)
compilers since forever generated code that constructs a value at certain
location (according to calling conventions/etc) and callee (or caller in
case of RVO) simply assumes ownership of that object. In language it was
represented as optional optimization and this was constantly PITA for
everyone. Finally, after 3 decades it was made mandatory -- which is still
unnecessary complication. Related semantic (caller constructs and passes
ownership to callee) should simply be enshrined in the standard and this
idea that parameters somehow gets copied into function scope (but compiler
probably will optimize it away) -- forgotten like a bad dream.
Heap allocation elision looks very similar to copy elision -- in both cases
it is an optional optimization that you can't rely on. I bet in 30 years
after much of hand wringing it will be made mandatory.
There is another side effect of heap elision -- it makes calculating stack
size requirement hard. I like the idea of writing completely correct code
-- that is code that will run forever and gracefully handle any
circumstance (including OOMs) as long as language runtime, hardware and all
other layers don't break promises they made. In C++ this (almost
<https://stackoverflow.com/questions/45497684/what-happens-if-throw-fails-to-allocate-memory-for-exception-object>)
can be achieved by calculating maximum stack size (via code analysis) and
reserving it at the start of the program. Heap allocation elision makes it
harder. Me don't like it.
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6%3DXnuHb0aaitCj6%3DChyoBG%3Dhej5GXAZZi6ysnSb5CAbA%40mail.gmail.com.
--94eb2c0e5d9ad584a40566dd97f9
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Mar 7, 2018 at 8:29 AM, Todd Fleming <span dir=3D"ltr"><<a href=3D"m=
ailto:tbfleming@gmail.com" target=3D"_blank">tbfleming@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=
=3D"">On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><div>There is a talk given by Gor about "disappearing=
coroutines" where (assuming compiler has required optimizations) coro=
utine gets completely "inlined". He mentioned "heap allocati=
on elision" optimization there -- whih to me looks like a big mistake =
(just like copy elision was).</div><div><br></div></div></div></div></block=
quote><div><br></div></span><div>Heap elision has been around for quite a w=
hile in clang, long before coroutines. What's the big mistake with heap=
elision and copy elision? My code has benefited from both.</div></div></bl=
ockquote><div><br></div><div>Copy elision is an illusion, unnecessary compl=
ication -- all (decent) compilers since forever generated code that constru=
cts a value at certain location (according to calling conventions/etc) and =
callee (or caller in case of RVO) simply assumes ownership of that object. =
In language it was represented as optional optimization and this was consta=
ntly PITA for everyone. Finally, after 3 decades it was made mandatory -- w=
hich is still unnecessary complication. Related semantic (caller constructs=
and passes ownership to callee) should simply be enshrined in the standard=
and this idea that parameters somehow gets copied into function scope (but=
compiler probably will optimize it away) -- forgotten like a bad dream.</d=
iv><div><br></div><div>Heap allocation elision looks very similar to copy e=
lision -- in both cases it is an optional optimization that you can't r=
ely on. I bet in 30 years after much of hand wringing it will be made manda=
tory.</div><div><br></div><div>There is another side effect of heap elision=
-- it makes calculating stack size requirement hard. I like the idea of wr=
iting completely correct code -- that is code that will run forever and gra=
cefully handle any circumstance (including OOMs) as long as language runtim=
e, hardware and all other layers don't break promises they made. In C++=
this (<a href=3D"https://stackoverflow.com/questions/45497684/what-happens=
-if-throw-fails-to-allocate-memory-for-exception-object">almost</a>) can be=
achieved by calculating maximum stack size (via code analysis) and reservi=
ng it at the start of the program. Heap allocation elision makes it harder.=
Me don't like it.</div><div><br></div></div>-- <br><div class=3D"gmail=
_signature" data-smartmail=3D"gmail_signature">Sincerely yours,<br>Michael.=
</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6%3DXnuHb0aaitCj6%3DChyoBG%3=
Dhej5GXAZZi6ysnSb5CAbA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP=
6%3DXnuHb0aaitCj6%3DChyoBG%3Dhej5GXAZZi6ysnSb5CAbA%40mail.gmail.com</a>.<br=
/>
--94eb2c0e5d9ad584a40566dd97f9--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Wed, 7 Mar 2018 21:07:34 -0600
Raw View
--f4f5e807fe843826eb0566ddfaaa
Content-Type: text/plain; charset="UTF-8"
On Wed, Mar 7, 2018 at 8:51 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:
>>
>> On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:
>>>>
>>>> But you're not going to stop the Coroutines TS from becoming part of
>>>> the standard by presenting a solution that only solves a minor part of the
>>>> problem the TS is intended to solve.
>>>>
>>>
>> Damn it! My evil plans got foiled again!
>>
>> Well, all I wanted to hear is opinions on given approach -- because
>> fundamentally it changes very little in current proposal. Only instead of
>> hiding behind opaque "just a function" facade this coroutine hides behind
>> transparent "template" facade. The way I see it -- it makes implementation
>> (on compiler side) easier. Was this approach ever considered? If yes -- why
>> it was rejected?
>>
>
> Resumable function-style coroutines weren't "rejected", as I understand
> it. They just stopped running the race. The people proposing it never
> implemented it, while Gor took the time and effort to get a decent
> implementation into a shipping compiler for people to use. Gor iterated
> heavily on the proposal, while the others never really improved or changed.
>
> Coroutines TS has won essentially by default; the people behind it put in
> the work to prove that the idea functions, and its competition didn't.
>
I think you (and others) misunderstood my idea -- I do not advocate against
current proposal, I am aiming only at one aspect of it -- namely hiding
coroutine behind "plain function" declaration. In my idea compiler can
generate precisely same language constructs during coroutine
"instantiation" (as it does in current proposal) -- same Awaitable<T> as
return types, etc.
> > Which optimizations are we talking about?
>>
>> There is a talk given by Gor about "disappearing coroutines" where
>> (assuming compiler has required optimizations) coroutine gets completely
>> "inlined". He mentioned "heap allocation elision" optimization there --
>> whih to me looks like a big mistake (just like copy elision was).
>>
>
> Sure, but not every case of coroutines relies on that. Coroutines being
> completely inlined is primarily for generator coroutines, which again
> aren't exactly the primary use case for the feature.
>
And yet it is one of selling points -- unfortunately it requires optional
compiler optimization, i.e. you can't rely on it. Also, it requires
compiler to be able to observe coroutine body, which naturally leads to a
question -- "why hiding it behind 'plain function' facade at all?". Why
don't we allow user to make related decisions explicitly (like where
coroutine frame will be allocated).
Current proposal leads to a situation where I can't use coroutine in
*noexcept* function -- because I can't rely on compiler to use heap
allocation elision.
> > They look great for generators, but they require a lot more effort to
>> write genuine asynchronous function calls.
>>
>> No, not really... At least I don't see it.
>>
>
> OK, take this synchronous code:
>
> int sync_call(...)
> {
> auto val = some_function(...);
> return val + 1;
> }
>
> This is the async version of that, using `co_await`:
>
> std::future<int> async_call(...)
> {
> auto val = co_await std::async(some_function, ...);
> co_return val + 1;
> }
>
> Write the equivalent of `async_call` using your coroutines system. Here
> are the rules. You must invoke `std::async`. You must use `future::then` to
> resume the rest of `async_call`. Your function must return a `future<int>`
> (which the caller themselves can use `::then` on). Oh, and don't forget:
> the future returned from the `async` call may not be a `future<int>`;
> merely some type that can have one added to it, the result of which is
> convertible to `int`.
>
coroutine int coro_call(...)
{
auto val = std::coro_async(some_function, ...)();
return val + 1;
}
or (if compiler treats certain function calls made from coroutine in a
special way (based on function signature, for example)):
coroutine int coro_call(...)
{
auto val = std::async(some_function, ...);
return val + 1;
}
you can come up with a bunch of interesting transformation for "coroutine
translation" step, but discussing them was not the goal of my original post.
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7440gR1R%3DcJasuYsH7fCu%3Dy1zPH8%2Bc--OuU1qcCi%3D%2BnA%40mail.gmail.com.
--f4f5e807fe843826eb0566ddfaaa
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Mar 7, 2018 at 8:51 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"ma=
ilto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=
=3D"">On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrot=
e:</span><span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote">On Tue, Mar 6, 2018 at 11:33 PM, N=
icol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span>=
On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:<block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">But you're not going=
to stop the Coroutines TS from becoming part of the standard by presenting=
a solution that only solves a minor part of the problem the TS is intended=
to solve.<br></div></blockquote></span></div></blockquote><div><br></div><=
div>Damn it! My evil plans got foiled again!</div><div><br></div><div>Well,=
all I wanted to hear is opinions on given approach -- because fundamentall=
y it changes very little in current proposal. Only instead of hiding behind=
opaque "just a function" facade this coroutine hides behind tran=
sparent "template" facade. The way I see it -- it makes implement=
ation (on compiler side) easier. Was this approach ever considered? If yes =
-- why it was rejected?</div></div></div></div></blockquote></span><div><br=
>Resumable function-style coroutines weren't "rejected", as I=
understand it. They just stopped running the race. The people proposing it=
never implemented it, while Gor took the time and effort to get a decent i=
mplementation into a shipping compiler for people to use. Gor iterated heav=
ily on the proposal, while the others never really improved or changed.<br>=
<br>Coroutines TS has won essentially by default; the people behind it put =
in the work to prove that the idea functions, and its competition didn'=
t.<br></div></div></blockquote><div><br></div><div>I think you (and others)=
misunderstood my idea -- I do not advocate against current proposal, I am =
aiming only at one aspect of it -- namely hiding coroutine behind "pla=
in function" declaration. In my idea compiler can generate precisely s=
ame language constructs during coroutine "instantiation" (as it d=
oes in current proposal) -- same Awaitable<T> as return types, etc.=
=C2=A0</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><span class=3D""><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">Which optimiz=
ations are we talking about?</span>
</div><div><br></div><div>There is a talk given by Gor about "disappea=
ring coroutines" where (assuming compiler has required optimizations) =
coroutine gets completely "inlined". He mentioned "heap allo=
cation elision" optimization there -- whih to me looks like a big mist=
ake (just like copy elision was).</div></div></div></div></blockquote></spa=
n><div><br>Sure, but not every case of coroutines relies on that. Coroutine=
s being completely inlined is primarily for generator coroutines, which aga=
in aren't exactly the primary use case for the feature.<br></div></div>=
</blockquote><div><br></div><div>And yet it is one of selling points -- unf=
ortunately it requires optional compiler optimization, i.e. you can't r=
ely on it. Also, it requires compiler to be able to observe coroutine body,=
which naturally leads to a question -- "why hiding it behind 'pla=
in function' facade at all?". Why don't we allow user to make =
related decisions explicitly (like where coroutine frame will be allocated)=
..</div><div><br></div><div>Current proposal leads to a situation where I ca=
n't use coroutine in <i>noexcept</i> function -- because I can't re=
ly on compiler to use heap allocation elision.</div><div><br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"=
gmail_quote"><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">They look gre=
at for generators, but they require a lot more effort to write genuine asyn=
chronous function calls.</span>
</div><div><br></div><div>No, not really... At least I don't see it.</d=
iv></div></div></div></blockquote></span><div><br>OK, take this synchronous=
code:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px" class=3D"m_4863267269=
909432920prettyprint"><code class=3D"m_4863267269909432920prettyprint"><div=
class=3D"m_4863267269909432920subprettyprint"><span style=3D"color:#008" c=
lass=3D"m_4863267269909432920styled-by-prettify">int</span><span style=3D"c=
olor:#000" class=3D"m_4863267269909432920styled-by-prettify"> sync_call</sp=
an><span style=3D"color:#660" class=3D"m_4863267269909432920styled-by-prett=
ify">(...)</span><span style=3D"color:#000" class=3D"m_4863267269909432920s=
tyled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_4863267=
269909432920styled-by-prettify">{</span><span style=3D"color:#000" class=3D=
"m_4863267269909432920styled-by-prettify"><br>=C2=A0 </span><span style=3D"=
color:#008" class=3D"m_4863267269909432920styled-by-prettify">auto</span><s=
pan style=3D"color:#000" class=3D"m_4863267269909432920styled-by-prettify">=
val </span><span style=3D"color:#660" class=3D"m_4863267269909432920styled=
-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_4863267269909=
432920styled-by-prettify"> some_function</span><span style=3D"color:#660" c=
lass=3D"m_4863267269909432920styled-by-prettify">(...);</span><span style=
=3D"color:#000" class=3D"m_4863267269909432920styled-by-prettify"><br>=C2=
=A0 </span><span style=3D"color:#008" class=3D"m_4863267269909432920styled-=
by-prettify">return</span><span style=3D"color:#000" class=3D"m_48632672699=
09432920styled-by-prettify"> val </span><span style=3D"color:#660" class=3D=
"m_4863267269909432920styled-by-prettify">+</span><span style=3D"color:#000=
" class=3D"m_4863267269909432920styled-by-prettify"> </span><span style=3D"=
color:#066" class=3D"m_4863267269909432920styled-by-prettify">1</span><span=
style=3D"color:#660" class=3D"m_4863267269909432920styled-by-prettify">;</=
span><span style=3D"color:#000" class=3D"m_4863267269909432920styled-by-pre=
ttify"><br></span><span style=3D"color:#660" class=3D"m_4863267269909432920=
styled-by-prettify">}</span></div></code></div><br>This is the async versio=
n of that, using `co_await`:<br><br><div style=3D"background-color:rgb(250,=
250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"=
class=3D"m_4863267269909432920prettyprint"><code class=3D"m_48632672699094=
32920prettyprint"><div class=3D"m_4863267269909432920subprettyprint"><span =
style=3D"color:#000" class=3D"m_4863267269909432920styled-by-prettify">std<=
/span><span style=3D"color:#660" class=3D"m_4863267269909432920styled-by-pr=
ettify">::</span><span style=3D"color:#000" class=3D"m_4863267269909432920s=
tyled-by-prettify">future</span><span style=3D"color:#080" class=3D"m_48632=
67269909432920styled-by-prettify"><int></span><span style=3D"color:#0=
00" class=3D"m_4863267269909432920styled-by-prettify"> async_call</span><sp=
an style=3D"color:#660" class=3D"m_4863267269909432920styled-by-prettify">(=
....)</span><span style=3D"color:#000" class=3D"m_4863267269909432920styled-=
by-prettify"><br></span><span style=3D"color:#660" class=3D"m_4863267269909=
432920styled-by-prettify">{</span><span style=3D"color:#000" class=3D"m_486=
3267269909432920styled-by-prettify"><br>=C2=A0 </span><span style=3D"color:=
#008" class=3D"m_4863267269909432920styled-by-prettify">auto</span><span st=
yle=3D"color:#000" class=3D"m_4863267269909432920styled-by-prettify"> val <=
/span><span style=3D"color:#660" class=3D"m_4863267269909432920styled-by-pr=
ettify">=3D</span><span style=3D"color:#000" class=3D"m_4863267269909432920=
styled-by-prettify"> co_await std</span><span style=3D"color:#660" class=3D=
"m_4863267269909432920styled-by-prettify">::</span><span style=3D"color:#00=
0" class=3D"m_4863267269909432920styled-by-prettify">async</span><span styl=
e=3D"color:#660" class=3D"m_4863267269909432920styled-by-prettify">(</span>=
<span style=3D"color:#000" class=3D"m_4863267269909432920styled-by-prettify=
">some_function</span><span style=3D"color:#660" class=3D"m_486326726990943=
2920styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_48632=
67269909432920styled-by-prettify"> </span><span style=3D"color:#660" class=
=3D"m_4863267269909432920styled-by-prettify">...);</span><span style=3D"col=
or:#000" class=3D"m_4863267269909432920styled-by-prettify"><br>=C2=A0 co_re=
turn val </span><span style=3D"color:#660" class=3D"m_4863267269909432920st=
yled-by-prettify">+</span><span style=3D"color:#000" class=3D"m_48632672699=
09432920styled-by-prettify"> </span><span style=3D"color:#066" class=3D"m_4=
863267269909432920styled-by-prettify">1</span><span style=3D"color:#660" cl=
ass=3D"m_4863267269909432920styled-by-prettify">;</span><span style=3D"colo=
r:#000" class=3D"m_4863267269909432920styled-by-prettify"><br></span><span =
style=3D"color:#660" class=3D"m_4863267269909432920styled-by-prettify">}</s=
pan></div></code></div><br>Write the equivalent of `async_call` using your =
coroutines system. Here are the rules. You must invoke `std::async`. You mu=
st use `future::then` to resume the rest of `async_call`. Your function mus=
t return a `future<int>` (which the caller themselves can use `::then=
` on). Oh, and don't forget: the future returned from the `async` call =
may not be a `future<int>`; merely some type that can have one added =
to it, the result of which is convertible to `int`.<br></div></div></blockq=
uote><div><br></div><div>coroutine int coro_call(...)</div><div>{</div><div=
>=C2=A0 =C2=A0 auto val =3D std::coro_async(some_function, ...)();</div><di=
v>=C2=A0 =C2=A0 return val + 1;</div><div>}</div><div><br></div><div>or (if=
compiler treats certain function calls made from coroutine in a special wa=
y (based on function signature, for example)):<br></div><div><br></div><div=
>
<div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:sm=
all;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norma=
l;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;te=
xt-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(=
255,255,255);text-decoration-style:initial;text-decoration-color:initial">c=
oroutine int coro_call(...)</div><div style=3D"color:rgb(34,34,34);font-fam=
ily:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatur=
es:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;te=
xt-align:start;text-indent:0px;text-transform:none;white-space:normal;word-=
spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial=
;text-decoration-color:initial">{</div><div style=3D"color:rgb(34,34,34);fo=
nt-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-l=
igatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:i=
nitial;text-decoration-color:initial">=C2=A0 =C2=A0 auto val =3D std::async=
(some_function, ...);</div><div style=3D"color:rgb(34,34,34);font-family:ar=
ial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:nor=
mal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-ali=
gn:start;text-indent:0px;text-transform:none;white-space:normal;word-spacin=
g:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-=
decoration-color:initial">=C2=A0 =C2=A0 return val + 1;</div><div style=3D"=
color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style=
:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:=
400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);t=
ext-decoration-style:initial;text-decoration-color:initial">}</div><div sty=
le=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font=
-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-w=
eight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-trans=
form:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,=
255);text-decoration-style:initial;text-decoration-color:initial"><br></div=
></div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-=
size:small;font-style:normal;font-variant-ligatures:normal;font-variant-cap=
s:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent=
:0px;text-transform:none;white-space:normal;word-spacing:0px;background-col=
or:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:ini=
tial">you can come up with a bunch of interesting transformation for "=
coroutine translation" step, but discussing them was not the goal of m=
y original post.</div><div style=3D"color:rgb(34,34,34);font-family:arial,s=
ans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;f=
ont-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);text-decoration-style:initial;text-decor=
ation-color:initial"><br></div></div>-- <br><div class=3D"gmail_signature" =
data-smartmail=3D"gmail_signature">Sincerely yours,<br>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7440gR1R%3DcJasuYsH7fCu%3Dy1=
zPH8%2Bc--OuU1qcCi%3D%2BnA%40mail.gmail.com?utm_medium=3Demail&utm_source=
=3Dfooter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%=
2BnLVP7440gR1R%3DcJasuYsH7fCu%3Dy1zPH8%2Bc--OuU1qcCi%3D%2BnA%40mail.gmail.c=
om</a>.<br />
--f4f5e807fe843826eb0566ddfaaa--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 7 Mar 2018 19:33:53 -0800 (PST)
Raw View
------=_Part_1000_1547721463.1520480033063
Content-Type: multipart/alternative;
boundary="----=_Part_1001_939514921.1520480033064"
------=_Part_1001_939514921.1520480033064
Content-Type: text/plain; charset="UTF-8"
On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:
>
> On Wed, Mar 7, 2018 at 8:51 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Wednesday, March 7, 2018 at 1:29:30 AM UTC-5, Michael Kilburn wrote:
>>>
>>> On Tue, Mar 6, 2018 at 11:33 PM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Michael Kilburn wrote:
>>>>>
>>>>> But you're not going to stop the Coroutines TS from becoming part of
>>>>> the standard by presenting a solution that only solves a minor part of the
>>>>> problem the TS is intended to solve.
>>>>>
>>>>
>>> Damn it! My evil plans got foiled again!
>>>
>>> Well, all I wanted to hear is opinions on given approach -- because
>>> fundamentally it changes very little in current proposal. Only instead of
>>> hiding behind opaque "just a function" facade this coroutine hides behind
>>> transparent "template" facade. The way I see it -- it makes implementation
>>> (on compiler side) easier. Was this approach ever considered? If yes -- why
>>> it was rejected?
>>>
>>
>> Resumable function-style coroutines weren't "rejected", as I understand
>> it. They just stopped running the race. The people proposing it never
>> implemented it, while Gor took the time and effort to get a decent
>> implementation into a shipping compiler for people to use. Gor iterated
>> heavily on the proposal, while the others never really improved or changed.
>>
>> Coroutines TS has won essentially by default; the people behind it put in
>> the work to prove that the idea functions, and its competition didn't.
>>
>
> I think you (and others) misunderstood my idea -- I do not advocate
> against current proposal, I am aiming only at one aspect of it -- namely
> hiding coroutine behind "plain function" declaration.
>
But that's practically the point of the Coroutines TS design: that the
compiler generates the coroutine machinery based entirely on what is going
on inside of the function, not how the outside world uses it. And as will
be discussed below, the ramifications of changing "only one aspect of it"
fundamentally changes the nature of what you're talking about.
In my idea compiler can generate precisely same language constructs during
> coroutine "instantiation" (as it does in current proposal) -- same
> Awaitable<T> as return types, etc.
>
>
>
>> > Which optimizations are we talking about?
>>>
>>> There is a talk given by Gor about "disappearing coroutines" where
>>> (assuming compiler has required optimizations) coroutine gets completely
>>> "inlined". He mentioned "heap allocation elision" optimization there --
>>> whih to me looks like a big mistake (just like copy elision was).
>>>
>>
>> Sure, but not every case of coroutines relies on that. Coroutines being
>> completely inlined is primarily for generator coroutines, which again
>> aren't exactly the primary use case for the feature.
>>
>
> And yet it is one of selling points -- unfortunately it requires optional
> compiler optimization, i.e. you can't rely on it. Also, it requires
> compiler to be able to observe coroutine body, which naturally leads to a
> question -- "why hiding it behind 'plain function' facade at all?". Why
> don't we allow user to make related decisions explicitly (like where
> coroutine frame will be allocated).
>
> Current proposal leads to a situation where I can't use coroutine in
> *noexcept* function -- because I can't rely on compiler to use heap
> allocation elision.
>
If it's a concern, trap the exception so that it doesn't try to exit the
`noexcept` function.
> They look great for generators, but they require a lot more effort to
>>> write genuine asynchronous function calls.
>>>
>>> No, not really... At least I don't see it.
>>>
>>
>> OK, take this synchronous code:
>>
>> int sync_call(...)
>> {
>> auto val = some_function(...);
>> return val + 1;
>> }
>>
>> This is the async version of that, using `co_await`:
>>
>> std::future<int> async_call(...)
>> {
>> auto val = co_await std::async(some_function, ...);
>> co_return val + 1;
>> }
>>
>> Write the equivalent of `async_call` using your coroutines system. Here
>> are the rules. You must invoke `std::async`. You must use `future::then` to
>> resume the rest of `async_call`. Your function must return a `future<int>`
>> (which the caller themselves can use `::then` on). Oh, and don't forget:
>> the future returned from the `async` call may not be a `future<int>`;
>> merely some type that can have one added to it, the result of which is
>> convertible to `int`.
>>
>
> coroutine int coro_call(...)
> {
> auto val = std::coro_async(some_function, ...)();
> return val + 1;
> }
>
You broke the rules. You didn't invoke `std::async`; you made a new
function. Under this design, any asynchronous library will have to have
`coro_` versions of all of its asynchronous functions, rather than just
using `future`s or similar such types that allow you to apply continuations
to them.
Also, note that this function *doesn't* return a `future<int>`. Which means
that if the user wants to use a continuation, they actually can't. Indeed,
the user can't even call it like a regular function, can they? Since it may
halt mid-stream, you have to either qualify the call to it in some
synchronization primitive or the caller themselves must be a `coroutine`
function that can therefore be halted.
By contrast, a coroutine function can *always* be called just like a
regular function. It has the specified return value, and behaves exactly
like its signature says it does. This fact is a fundamental part of the
system's design.
The kind of design you've presented is exactly what the resumable
expressions proposal used
<http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>. Only it
was a bit cleverer about it, such that you would just have a resumable
function called "await" that could be overloaded for some "awaitable" type,
which would do the scheduling and unpacking, returning the unpacked value
once resumed.
You really should look at that proposal; it's clearly what you want. And
yes, it was looked at, but it didn't move forward past P0114R0.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d510549a-6314-4911-89c5-8bcdf15b029b%40isocpp.org.
------=_Part_1001_939514921.1520480033064
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael =
Kilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div><div class=3D"gmail_quote">On Wed, Mar 7, 2018 at 8:51 AM, Nicol Bola=
s <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfus=
cated-mailto=3D"ADUo39EpBAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&=
#39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&=
#39;;return true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><span>On Wednesday, March 7, 2018 at 1:2=
9:30 AM UTC-5, Michael Kilburn wrote:</span><span><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote">On Tue, Mar=
6, 2018 at 11:33 PM, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow"=
>jmck...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><span>On Tuesday, March 6, 2018 at 5:02:02 PM UTC-5, Micha=
el Kilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin=
-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">B=
ut you're not going to stop the Coroutines TS from becoming part of the=
standard by presenting a solution that only solves a minor part of the pro=
blem the TS is intended to solve.<br></div></blockquote></span></div></bloc=
kquote><div><br></div><div>Damn it! My evil plans got foiled again!</div><d=
iv><br></div><div>Well, all I wanted to hear is opinions on given approach =
-- because fundamentally it changes very little in current proposal. Only i=
nstead of hiding behind opaque "just a function" facade this coro=
utine hides behind transparent "template" facade. The way I see i=
t -- it makes implementation (on compiler side) easier. Was this approach e=
ver considered? If yes -- why it was rejected?</div></div></div></div></blo=
ckquote></span><div><br>Resumable function-style coroutines weren't &qu=
ot;rejected", as I understand it. They just stopped running the race. =
The people proposing it never implemented it, while Gor took the time and e=
ffort to get a decent implementation into a shipping compiler for people to=
use. Gor iterated heavily on the proposal, while the others never really i=
mproved or changed.<br><br>Coroutines TS has won essentially by default; th=
e people behind it put in the work to prove that the idea functions, and it=
s competition didn't.<br></div></div></blockquote><div><br></div><div>I=
think you (and others) misunderstood my idea -- I do not advocate against =
current proposal, I am aiming only at one aspect of it -- namely hiding cor=
outine behind "plain function" declaration.</div></div></div></di=
v></blockquote><div><br>But that's practically the point of the Corouti=
nes TS design: that the compiler generates the coroutine machinery based en=
tirely on what is going on inside of the function, not how the outside worl=
d uses it. And as will be discussed below, the ramifications of changing &q=
uot;only one aspect of it" fundamentally changes the nature of what yo=
u're talking about.<br><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>In my idea com=
piler can generate precisely same language constructs during coroutine &quo=
t;instantiation" (as it does in current proposal) -- same Awaitable<=
;T> as return types, etc. =C2=A0</div></div></div></div></blockquote><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><div><div class=3D"gmail_quote"><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">Which optimiz=
ations are we talking about?</span>
</div><div><br></div><div>There is a talk given by Gor about "disappea=
ring coroutines" where (assuming compiler has required optimizations) =
coroutine gets completely "inlined". He mentioned "heap allo=
cation elision" optimization there -- whih to me looks like a big mist=
ake (just like copy elision was).</div></div></div></div></blockquote></spa=
n><div><br>Sure, but not every case of coroutines relies on that. Coroutine=
s being completely inlined is primarily for generator coroutines, which aga=
in aren't exactly the primary use case for the feature.<br></div></div>=
</blockquote><div><br></div><div>And yet it is one of selling points -- unf=
ortunately it requires optional compiler optimization, i.e. you can't r=
ely on it. Also, it requires compiler to be able to observe coroutine body,=
which naturally leads to a question -- "why hiding it behind 'pla=
in function' facade at all?". Why don't we allow user to make =
related decisions explicitly (like where coroutine frame will be allocated)=
..</div><div><br></div><div>Current proposal leads to a situation where I ca=
n't use coroutine in <i>noexcept</i> function -- because I can't re=
ly on compiler to use heap allocation elision.</div></div></div></div></blo=
ckquote><div><br>If it's a concern, trap the exception so that it doesn=
't try to exit the `noexcept` function.<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_q=
uote"><div>>=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);float:none;display:inline">They look gre=
at for generators, but they require a lot more effort to write genuine asyn=
chronous function calls.</span>
</div><div><br></div><div>No, not really... At least I don't see it.</d=
iv></div></div></div></blockquote></span><div><br>OK, take this synchronous=
code:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span styl=
e=3D"color:#008">int</span><span style=3D"color:#000"> sync_call</span><spa=
n style=3D"color:#660">(...)</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </sp=
an><span style=3D"color:#008">auto</span><span style=3D"color:#000"> val </=
span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> some_=
function</span><span style=3D"color:#660">(...);</span><span style=3D"color=
:#000"><br>=C2=A0 </span><span style=3D"color:#008">return</span><span styl=
e=3D"color:#000"> val </span><span style=3D"color:#660">+</span><span style=
=3D"color:#000"> </span><span style=3D"color:#066">1</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#660">}</span></div></code></div><br>This is the async version of that, =
using `co_await`:<br><br><div style=3D"background-color:rgb(250,250,250);bo=
rder-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div=
><span style=3D"color:#000">std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">future</span><span style=3D"color:#080"><int&g=
t;</span><span style=3D"color:#000"> async_call</span><span style=3D"color:=
#660">(...)</span><span style=3D"color:#000"><br></span><span style=3D"colo=
r:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D=
"color:#008">auto</span><span style=3D"color:#000"> val </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> co_await std</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#000">async</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">some_function</=
span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">...);</span><span style=3D"color:#000"><br>=C2=
=A0 co_return val </span><span style=3D"color:#660">+</span><span style=3D"=
color:#000"> </span><span style=3D"color:#066">1</span><span style=3D"color=
:#660">;</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
660">}</span></div></code></div><br>Write the equivalent of `async_call` us=
ing your coroutines system. Here are the rules. You must invoke `std::async=
`. You must use `future::then` to resume the rest of `async_call`. Your fun=
ction must return a `future<int>` (which the caller themselves can us=
e `::then` on). Oh, and don't forget: the future returned from the `asy=
nc` call may not be a `future<int>`; merely some type that can have o=
ne added to it, the result of which is convertible to `int`.<br></div></div=
></blockquote><div><br></div><div>coroutine int coro_call(...)</div><div>{<=
/div><div>=C2=A0 =C2=A0 auto val =3D std::coro_async(some_function, ...)();=
</div><div>=C2=A0 =C2=A0 return val + 1;</div><div>}</div></div></div></div=
></blockquote><div><br>You broke the rules. You didn't invoke `std::asy=
nc`; you made a new function. Under this design, any asynchronous library w=
ill have to have `coro_` versions of all of its asynchronous functions, rat=
her than just using `future`s or similar such types that allow you to apply=
continuations to them.<br><br>Also, note that this function <i>doesn't=
</i> return a `future<int>`. Which means that if the user wants to us=
e a continuation, they actually can't. Indeed, the user can't even =
call it like a regular function, can they? Since it may halt mid-stream, yo=
u have to either qualify the call to it in some synchronization primitive o=
r the caller themselves must be a `coroutine` function that can therefore b=
e halted.<br><br>By contrast, a coroutine function can *always* be called j=
ust like a regular function. It has the specified return value, and behaves=
exactly like its signature says it does. This fact is a fundamental part o=
f the system's design.<br><br>The kind of design you've presented i=
s <a href=3D"http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pd=
f">exactly what the resumable expressions proposal used</a>. Only it was a =
bit cleverer about it, such that you would just have a resumable function c=
alled "await" that could be overloaded for some "awaitable&q=
uot; type, which would do the scheduling and unpacking, returning the unpac=
ked value once resumed.<br><br>You really should look at that proposal; it&=
#39;s clearly what you want. And yes, it was looked at, but it didn't m=
ove forward past P0114R0.</div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/d510549a-6314-4911-89c5-8bcdf15b029b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d510549a-6314-4911-89c5-8bcdf15b029b=
%40isocpp.org</a>.<br />
------=_Part_1001_939514921.1520480033064--
------=_Part_1000_1547721463.1520480033063--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Thu, 8 Mar 2018 03:54:18 -0600
Raw View
--94eb2c0c8b1ac7a7230566e3a80b
Content-Type: text/plain; charset="UTF-8"
On Thu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <crusader.mike@gmail.com>
wrote:
> i.e. idea is not about coroutine implementation or semantic of generated
> functions -- it is about having every client to see entire coroutine. At
> this stage I really don't care exactly how resulting state machine will
> behave or what methods it will expose.
>
One more argument -- consider template class and stackless coroutine. Both
of them are language provided mechanisms for transforming some code into a
C++ class -- i.e. fundamentally they do the same thing. In case of template
class there is no way to hide it's declaration from users -- at any point
entire class definition is visible to every user (even though you may tuck
away definition of individual member functions into some TU). Stackless
coroutine (in current form) hides resulting class -- this lack of symmetry
bothers me. It forces designers to come up with mechanisms designed to
workaround resulting problems (e.g. heap allocation elision allows us to
delegate allocation to a party that knows state machine frame size and move
allocation to stack, if certain criteria are met).
Regards,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7bMyWf41uV00jMWKMqCQo_SLKdku-hGYmTpsvWJar-eg%40mail.gmail.com.
--94eb2c0c8b1ac7a7230566e3a80b
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <span dir=3D"ltr"><<a href=
=3D"mailto:crusader.mike@gmail.com" target=3D"_blank">crusader.mike@gmail.c=
om</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>i.e. idea is no=
t about coroutine implementation or semantic of generated functions -- it i=
s about having every client to see entire coroutine. At this stage I really=
don't care exactly how resulting state machine will behave or what met=
hods it will expose.<br></div></div></div></div></blockquote><div><br></div=
><div>One more argument -- consider template class and stackless coroutine.=
Both of them are language provided mechanisms for transforming some code i=
nto a C++ class -- i.e. fundamentally they do the same thing. In case of te=
mplate class there is no way to hide it's declaration from users -- at =
any point entire class definition is visible to every user (even though you=
may tuck away definition of individual member functions into some TU). Sta=
ckless coroutine (in current form) hides resulting class -- this lack of sy=
mmetry bothers me. It forces designers to come up with mechanisms designed =
to workaround resulting problems (e.g. heap allocation elision allows us to=
delegate allocation to a party that knows state machine frame size and mov=
e allocation to stack, if certain criteria are met).</div><div><br></div><d=
iv><br></div><div>Regards,</div><div>Michael.</div><div><br></div><div><br>=
</div><div><br></div></div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7bMyWf41uV00jMWKMqCQo_SLKdku=
-hGYmTpsvWJar-eg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7bMyWf=
41uV00jMWKMqCQo_SLKdku-hGYmTpsvWJar-eg%40mail.gmail.com</a>.<br />
--94eb2c0c8b1ac7a7230566e3a80b--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Thu, 8 Mar 2018 00:15:35 -0600
Raw View
--001a114af56896712a0566e09ab9
Content-Type: text/plain; charset="UTF-8"
On Wed, Mar 7, 2018 at 9:33 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:
>>
>> I think you (and others) misunderstood my idea -- I do not advocate
>> against current proposal, I am aiming only at one aspect of it -- namely
>> hiding coroutine behind "plain function" declaration.
>>
>
> But that's practically the point of the Coroutines TS design: that the
> compiler generates the coroutine machinery based entirely on what is going
> on inside of the function, not how the outside world uses it. And as will
> be discussed below, the ramifications of changing "only one aspect of it"
> fundamentally changes the nature of what you're talking about.
>
I am sticking to my guns (i.e. going to claim I am being misunderstood).
I'll try to explain it again:
- stackless coroutines is when your code gets transformed int a C++ object
which represents a state machine (and associated fluff to tie it with the
rest of your code)
- the idea is to use template-like approach to "transformation" step -- as
far as I am concerned it could generate exactly the same declarations as
you write in MSVC version that supports Gor's proposal. I.e.
coroutine int mc(...) { ...; coro2(); ... }
could result in generating:
future<int> mc(...) { ...; co_await coro2(); ... }
or any other representation -- I really don't care.
But the difference is that all translation units will see everything,
unlike current state where (typically) only one will have a full vision.
This would allow every call site to know everything about generated state
machine (e.g. it's size). This will allow certain features:
- caller can explicitly control location of coroutine frame
- a coroutine will be clearly different from a function -- which would
allow to avoid necessity of co_await or co_return. Compiler can see that
current coroutine calls another coroutine and generate required fluff
automatically. You can introduce a new keyword (or convention) that will
allow you to call coroutine in other way (but I doubt this need will be
great).
- inlining of some of generated C++ object methods
- you need to update only one portion of compiler -- one that transforms
coroutine declarations into state machine class declaration. No need to
introduce additional logic in other areas.
- etc
i.e. idea is not about coroutine implementation or semantic of generated
functions -- it is about having every client to see entire coroutine. At
this stage I really don't care exactly how resulting state machine will
behave or what methods it will expose.
> And yet it is one of selling points -- unfortunately it requires optional
>> compiler optimization, i.e. you can't rely on it. Also, it requires
>> compiler to be able to observe coroutine body, which naturally leads to a
>> question -- "why hiding it behind 'plain function' facade at all?". Why
>> don't we allow user to make related decisions explicitly (like where
>> coroutine frame will be allocated).
>>
>
>> Current proposal leads to a situation where I can't use coroutine in
>> *noexcept* function -- because I can't rely on compiler to use heap
>> allocation elision.
>>
>
> If it's a concern, trap the exception so that it doesn't try to exit the
> `noexcept` function.
>
Nope, I know I can build noexcept function that can count to ten. But I
can't do it with coroutines -- because I can't force it's frame to be on
stack (it is an optional optimization). Catching std::bad_alloc gives me
nothing -- what I am going to do when I caught it -- call std::terminate()?
You broke the rules. You didn't invoke `std::async`; you made a new
> function. Under this design, any asynchronous library will have to have
> `coro_` versions of all of its asynchronous functions, rather than just
> using `future`s or similar such types that allow you to apply continuations
> to them.
>
I see... one of the aims is to integrate coroutines with future/async
stuff... I am probably behind on all this. All async libs I looked at used
same approach -- public API consists of a function (async_foo) that takes a
callback. Then someone somewhere cranks the event loop which eventually
calls "process_events()" library function that in turn calls aforementioned
callback.
So, for this library to add coroutine support you'd have to create second
inline function (or macro) coro_foo() that takes address of resume() method
of current coroutine, registers it using async_foo() and suspends current
coroutine. I.e. in this design you still have to add second version of your
async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fault is this
approach -- everything is clear and clean.
Now, if library instead exports "future<int> foo()" -- there is no need for
coro_foo(), but implementation becomes less efficient and more complex.
Because of type erasures, having to allocate memory, having to move values
and other stuff (like synchronization). Am I right? Is it a good price for
not having to add a (rather simple) coro_foo()?
Also, note that this function *doesn't* return a `future<int>`. Which means
> that if the user wants to use a continuation, they actually can't. Indeed,
> the user can't even call it like a regular function, can they? Since it may
> halt mid-stream, you have to either qualify the call to it in some
> synchronization primitive or the caller themselves must be a `coroutine`
> function that can therefore be halted.
>
it isn't a function -- it is a coroutine. Transforming it may result in a
function that returns future<int> (I don't have a "new design" -- all I
presented was a simple idea that is very far from being a "design").
Yes, you can't invoke coro_call() from a normal function (unless it is
inline and is called from another coroutine). But you could create an
instance of it (i.e. create an instance of state machine class that
coro_call's transformation produces). And (depending on generated class
interface) call it's public methods.
> By contrast, a coroutine function can *always* be called just like a
> regular function. It has the specified return value, and behaves exactly
> like its signature says it does. This fact is a fundamental part of the
> system's design.
>
Yes, because from courotine is hidden behind "plain function" facade. Thus
hiding state machine details from the caller -- it's frame size, it's
methods, etc. All you have is "future<int> myname(...);". Some details get
hidden in futures<int> which introduce an (arguably unnecessary) layer of
indirection. This layer disappears if "transformation" step described above
generates state machine class visible in it's entirety in every TU that
uses it.
> The kind of design you've presented is exactly what the resumable
> expressions proposal used
> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>. Only
> it was a bit cleverer about it, such that you would just have a resumable
> function called "await" that could be overloaded for some "awaitable" type,
> which would do the scheduling and unpacking, returning the unpacked value
> once resumed.
>
> You really should look at that proposal; it's clearly what you want. And
> yes, it was looked at, but it didn't move forward past P0114R0.
>
Thank you, I will read it. But as I said -- it isn't what I was talking
about. I am probably not the best communicator.
In any case -- I am not insisting that this is a brilliant idea that will
turn the world on it's head. Just asking for opinions and if it was already
considered.
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6W_W8dB%3Dwsc%3Dp%3DJWPu_1fvfNQvcvUKn1tt7nkWiVZHfg%40mail.gmail.com.
--001a114af56896712a0566e09ab9
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Mar 7, 2018 at 9:33 PM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"ma=
ilto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></sp=
an> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Wednesday,=
March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:<span class=3D""=
><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gma=
il_quote">I think you (and others) misunderstood my idea -- I do not advoca=
te against current proposal, I am aiming only at one aspect of it -- namely=
hiding coroutine behind "plain function" declaration.<br></div><=
/div></blockquote></span></div></blockquote><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><div><br>But that's practically the point of the Corou=
tines TS design: that the compiler generates the coroutine machinery based =
entirely on what is going on inside of the function, not how the outside wo=
rld uses it. And as will be discussed below, the ramifications of changing =
"only one aspect of it" fundamentally changes the nature of what =
you're talking about.<br></div></div></blockquote><div><br></div><div>I=
am sticking to my guns (i.e. going to claim I am being misunderstood). I&#=
39;ll try to explain it again:</div><div>- stackless coroutines is when you=
r code gets transformed int a C++ object which represents a state machine (=
and associated fluff to tie it with the rest of your code)</div><div>- the =
idea is to use template-like approach to "transformation" step --=
as far as I am concerned it could generate exactly the same declarations a=
s you write in MSVC version that supports Gor's proposal. I.e.</div><di=
v><br></div><div>coroutine int mc(...) { ...; coro2(); ... }</div><div><br>=
</div><div>could result in generating:</div><div><br></div><div>future<i=
nt> mc(...) { ...; co_await=C2=A0=C2=A0coro2(); ... }</div><div><br></di=
v><div>or any other representation -- I really don't care.</div><div><b=
r></div><div>But the difference is that all translation units will see ever=
ything, unlike current state where (typically) only one will have a full vi=
sion. This would allow every call site to know everything about generated s=
tate machine (e.g. it's size). This will allow certain features:</div><=
div>- caller can explicitly control location of coroutine frame</div><div>-=
a coroutine will be clearly different from a function -- which would allow=
to avoid necessity of co_await or co_return. Compiler can see that current=
coroutine calls another coroutine and generate required fluff automaticall=
y. You can introduce a new keyword (or convention) that will allow you to c=
all coroutine in other way (but I doubt this need will be great).</div><div=
>- inlining of some of generated C++ object methods</div><div>- you need to=
update only one portion of compiler -- one that transforms coroutine decla=
rations into state machine class declaration. No need to introduce addition=
al logic in other areas.</div><div>- etc<br></div><div><br></div><div>i.e. =
idea is not about coroutine implementation or semantic of generated functio=
ns -- it is about having every client to see entire coroutine. At this stag=
e I really don't care exactly how resulting state machine will behave o=
r what methods it will expose.</div><div><br></div><div>=C2=A0<br></div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote">And =
yet it is one of selling points -- unfortunately it requires optional compi=
ler optimization, i.e. you can't rely on it. Also, it requires compiler=
to be able to observe coroutine body, which naturally leads to a question =
-- "why hiding it behind 'plain function' facade at all?"=
.. Why don't we allow user to make related decisions explicitly (like wh=
ere coroutine frame will be allocated).<br></div></div></blockquote><blockq=
uote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote=
"><div><br></div><div>Current proposal leads to a situation where I can'=
;t use coroutine in <i>noexcept</i> function -- because I can't rely on=
compiler to use heap allocation elision.</div></div></div></blockquote></s=
pan><div><br>If it's a concern, trap the exception so that it doesn'=
;t try to exit the `noexcept` function.<br></div></div></blockquote><div><b=
r></div><div>Nope, I know I can build noexcept function that can count to t=
en. But I can't do it with coroutines -- because I can't force it&#=
39;s frame to be on stack (it is an optional optimization). Catching std::b=
ad_alloc gives me nothing -- what I am going to do when I caught it -- call=
std::terminate()?</div><div><br></div><div><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(20=
4,204,204);padding-left:1ex"><div dir=3D"ltr"><span class=3D""><div dir=3D"=
ltr"><div><div class=3D"gmail_quote"><div dir=3D"ltr"><span><div dir=3D"ltr=
"><div><div class=3D"gmail_quote"><div>You broke the rules. You didn't =
invoke `std::async`; you made a new function. Under this design, any asynch=
ronous library will have to have `coro_` versions of all of its asynchronou=
s functions, rather than just using `future`s or similar such types that al=
low you to apply continuations to them.<br></div></div></div></div></span><=
/div></div></div></div></span></div></blockquote><div><br></div><div>I see.=
... one of the aims is to integrate coroutines with future/async stuff... I =
am probably behind on all this. All async libs I looked at used same approa=
ch -- public API consists of a function (async_foo) that takes a callback. =
Then someone somewhere cranks the event loop which eventually calls "p=
rocess_events()" library function that in turn calls aforementioned ca=
llback.</div><div><br></div><div>So, for this library to add coroutine supp=
ort you'd have to create second inline function (or macro) coro_foo() t=
hat takes address of resume() method of current coroutine, registers it usi=
ng async_foo() and suspends current coroutine. I.e. in this design you stil=
l have to add second version of your async_foo() -- a coroutine-aware wrapp=
er coro_foo(). I see no fault is this approach -- everything is clear and c=
lean.</div><div><br></div><div>Now, if library instead exports "future=
<int> foo()" -- there is no need for coro_foo(), but implementat=
ion becomes less efficient and more complex. Because of type erasures, havi=
ng to allocate memory, having to move values and other stuff (like synchron=
ization). Am I right? Is it a good price for not having to add a (rather si=
mple) coro_foo()?</div><div><br></div><div><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div>Also, note that this function <i>doesn't=
</i> return a `future<int>`. Which means that if the user wants to us=
e a continuation, they actually can't. Indeed, the user can't even =
call it like a regular function, can they? Since it may halt mid-stream, yo=
u have to either qualify the call to it in some synchronization primitive o=
r the caller themselves must be a `coroutine` function that can therefore b=
e halted.<br></div></div></blockquote><div><br></div><div>it isn't a fu=
nction -- it is a coroutine. Transforming it may result in a function that =
returns future<int> (I don't have a "new design" -- all=
I presented was a simple idea that is very far from being a "<span st=
yle=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;fon=
t-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-=
weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tran=
sform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255=
,255);text-decoration-style:initial;text-decoration-color:initial;float:non=
e;display:inline">design</span>").</div><div><br></div><div>Yes, you c=
an't invoke coro_call() from a normal function (unless it is inline and=
is called from another coroutine). But you could create an instance of it =
(i.e. create an instance of state machine class that coro_call's transf=
ormation produces). And (depending on generated class interface) call it=
9;s public methods.</div><div><br></div><div>=C2=A0<br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>By contrast, a coroutine function ca=
n *always* be called just like a regular function. It has the specified ret=
urn value, and behaves exactly like its signature says it does. This fact i=
s a fundamental part of the system's design.<br></div></div></blockquot=
e><div><br></div><div>Yes, because from courotine is hidden behind "pl=
ain function" facade. Thus hiding state machine details from the calle=
r -- it's frame size, it's methods, etc. All you have is "futu=
re<int> myname(...);". Some details get hidden in futures<int=
> which introduce an (arguably unnecessary) layer of indirection. This l=
ayer disappears if "transformation" step described above generate=
s state machine class visible in it's entirety in every TU that uses it=
..</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><div>The kind of design you've presented is <a href=3D"http=
://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf" target=3D"_bla=
nk">exactly what the resumable expressions proposal used</a>. Only it was a=
bit cleverer about it, such that you would just have a resumable function =
called "await" that could be overloaded for some "awaitable&=
quot; type, which would do the scheduling and unpacking, returning the unpa=
cked value once resumed.=C2=A0</div></div></blockquote><blockquote class=3D=
"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding=
-left:1ex"><div dir=3D"ltr"><div><br>You really should look at that proposa=
l; it's clearly what you want. And yes, it was looked at, but it didn&#=
39;t move forward past P0114R0.</div></div></blockquote><div><br></div><div=
>Thank you, I will read it. But as I said -- it isn't what I was talkin=
g about. I am probably not the best communicator.<br></div><div><br></div><=
div>In any case -- I am not insisting that this is a brilliant idea that wi=
ll turn the world on it's head. Just asking for opinions and if it was =
already considered.</div><div><br></div><div><br></div></div>-- <br><div cl=
ass=3D"gmail_signature" data-smartmail=3D"gmail_signature">Sincerely yours,=
<br>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6W_W8dB%3Dwsc%3Dp%3DJWPu_1fv=
fNQvcvUKn1tt7nkWiVZHfg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP=
6W_W8dB%3Dwsc%3Dp%3DJWPu_1fvfNQvcvUKn1tt7nkWiVZHfg%40mail.gmail.com</a>.<br=
/>
--001a114af56896712a0566e09ab9--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Thu, 8 Mar 2018 01:09:19 -0600
Raw View
--f403045fc1aecbd0750566e15a6c
Content-Type: text/plain; charset="UTF-8"
On Wed, Mar 7, 2018 at 11:17 AM, Lee Howes <xrikcus@gmail.com> wrote:
> > Gor iterated heavily on the proposal, while the others never really
> improved or changed.
>
> Oliver Kowalke has updated his series of fibers papers:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf so
> there is continued work on the stackful coroutines approach, at least in
> the sense of the required primitives.
>
Well, as I understand Microsoft sponsors Gor's work -- it isn't surprising
that his proposal progresses faster and more favored by committee who's
activities are coincidentally sponsored by MS too. :-)
But "evil corporation" jokes aside -- I don't see stackful coroutine as a
competitor to stackless one. Latter one is essentially a C++ state machine
class generated at compile time, while in former everything happens
dynamically at runtime. Plus it allows execution flow to jump around in a
"non-linear" way (i.e. A -> B -> C -> A switching).
Michael:
> On "having to propagate 'co_await's down the call tree doesn't seem
> ideal" for many of us this is absolutely ideal, it's so ideal that we've
> experimented with enforcing it even in fiber-based code that doesn't need
> it and this feature is one reason that may cause us to port some of our
> fiber-based code to these coroutines! The safety benefits of doing that
> are enormous in terms of enforcement of asynchronous interfaces,
> guaranteeing where code runs under complete control of caller and callee
> library constructs, and ensuring that different libraries do not interfere
> with each others' synchronisation primitives.
>
It seems I am missing a lot of background here -- how all these things are
related to fibers or co_await?
> We've actively been *removing* continuation support from futures in some
> parts of our codebase for similar reasons - explicitness has enormous
> value. A few weeks of extra work strengthening a library to make it trivial
> to use by a caller, while maintaining all the safety my library needs, is
> well worth the effort.
>
Same here -- how "continuation support of futures" are related to
"co_await"? Which (afaik) is a suspension marker for compiler and place
where we subscribe to "data-is-ready" event of another coroutine.
We clearly need to be able to co_await on opaque library calls - so there
> are going to be cases all over the codebase where the compiler can not, and
> indeed should not, have any visibility into the library code.
>
Nothing prevents you from hiding state machine object (generated from
couroutine declaration) behind a function manually -- in a similar way
current proposal does.
We even want coroutines to sit behind dynamic dispatch - is there any
> reason why a virtual function should not be a coroutine?
>
Ultimately, stackless coroutine is a C++ object with methods like
resume()/etc. I don't see why you shouldn't be able to treat it as such --
i.e. storing it as member variable of another class and access in a virtual
function.
Enforcing visibility to the compiler would break that. Those are cases
> where we will not get automatic heap elision. We may want explicit stack
> allocation instead and this can be implemented on top of the current TS,
> though some modifications would make it cleaner. We may not care because
> the odd heap allocation across asynchronous library interfaces is trivial,
> and we have worse than that now with synchronising promise/future pairs.
>
Yes, I think having ability to explicitly control where state machine is
allocated is a must.
Hmm... You know, I've spent more than 2 decades writing relatively complex
multithreaded (occasionally lockless) code and I never got into
future/async paradigm... Never really needed it.
A lot of work has gone into this, and while it is not perfect and there are
> certainly concerns from some parties with rushing it into the standard, on
> balance long years of discussions around similar questions to those you are
> asking have got us to this point.
>
Well, in this case I am trying to catch up with you. Can't do it without
asking questions.
Regards,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP5iYbJFx7f%2BoOPkbY%3D8HwtHXrpnszfWQmqFGOk_7u-1%3DQ%40mail.gmail.com.
--f403045fc1aecbd0750566e15a6c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On W=
ed, Mar 7, 2018 at 11:17 AM, Lee Howes <span dir=3D"ltr"><<a href=3D"mai=
lto:xrikcus@gmail.com" target=3D"_blank">xrikcus@gmail.com</a>></span> w=
rote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><=
div>>=C2=A0<span style=3D"color:rgb(34,34,34);font-family:arial,sans-ser=
if;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-va=
riant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;te=
xt-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;backg=
round-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-=
color:initial;float:none;display:inline">Gor iterated heavily on the propos=
al, while the others never really improved or changed.</span></div><div><sp=
an style=3D"font-size:12.8px">=C2=A0</span><br></div></span>Oliver Kowalke =
has updated his series of fibers papers:=C2=A0<a href=3D"http://www.open-st=
d.org/jtc1/sc22/wg21/docs/papers/2018/p0876r0.pdf" target=3D"_blank">http:/=
/www.open-std.<wbr>org/jtc1/sc22/wg21/docs/<wbr>papers/2018/p0876r0.pdf</a>=
so there is continued work on the stackful coroutines approach, at least i=
n the sense of the required primitives.</div></blockquote><div><br></div><d=
iv>Well, as I understand Microsoft sponsors Gor's work -- it isn't =
surprising that his proposal progresses faster and more favored by committe=
e who's activities are coincidentally sponsored by MS too. :-)</div><di=
v><br></div><div>But "evil corporation" jokes aside -- I don'=
t see stackful coroutine as a competitor to stackless one. Latter one is es=
sentially a C++ state machine class generated at compile time, while in for=
mer everything happens dynamically at runtime. Plus it allows execution flo=
w to jump around in a "non-linear" way (i.e. A -> B -> C -&=
gt; A switching).</div><div><br></div><div><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div>Michael:<br></div><div>On "<span style=
=3D"color:rgb(80,0,80);font-size:12.8px">having to propagate 'co_await&=
#39;s down the call tree doesn't seem ideal" for many of us this i=
s absolutely ideal, it's so ideal that we've experimented with enfo=
rcing it even in fiber-based code that doesn't need it and this feature=
is one reason that may cause us to port some of our fiber-based code to th=
ese coroutines!=C2=A0 The safety benefits of doing that are enormous in ter=
ms of enforcement of asynchronous interfaces, guaranteeing where code runs =
under complete control of caller and callee library constructs, and ensurin=
g that different libraries do not interfere with each others' synchroni=
sation primitives. </span></div></div></blockquote><div><br></div><div>It s=
eems I am missing a lot of background here -- how all these things are rela=
ted to fibers or co_await?</div><div><br></div><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><div><span style=3D"color:rgb(80,0,80)=
;font-size:12.8px">We've actively been *removing* continuation support =
from futures in some parts of our codebase for similar reasons - explicitne=
ss has enormous value. A few weeks of extra work strengthening a library to=
make it trivial to use by a caller, while maintaining all the safety my li=
brary needs, is well worth the effort.</span></div></div></blockquote><div>=
<br></div><div>Same here -- how "continuation support of futures"=
are related to "co_await"? Which (afaik) is a suspension marker =
for compiler and place where we subscribe to "data-is-ready" even=
t of another coroutine.</div><div><br></div><div><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div><span style=3D"font-size:12.8px;color:=
rgb(80,0,80)">We clearly need to be able to co_await on opaque library call=
s - so there are going to be cases all over the codebase where the compiler=
can not, and indeed should not, have any visibility into the library code.=
</span></div></div></blockquote><div><br></div><div>Nothing prevents you f=
rom hiding state machine object (generated from couroutine declaration) beh=
ind a function manually -- in a similar way current proposal does.</div><di=
v><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div><span style=3D"font-size:12.8px;color:rgb(80,0,80)">We even want corou=
tines to sit behind dynamic dispatch - is there any reason why a virtual fu=
nction should not be a coroutine? </span></div></div></blockquote><div><br>=
</div><div>Ultimately, stackless coroutine is a C++ object with methods lik=
e resume()/etc. I don't see why you shouldn't be able to treat it a=
s such -- i.e. storing it as member variable of another class and access in=
a virtual function.</div><div><br></div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div><span style=3D"font-size:12.8px;color:r=
gb(80,0,80)">Enforcing visibility to the compiler would break that. Those a=
re cases where we will not get automatic heap elision. We may want explicit=
stack allocation instead and this can be implemented on top of the current=
TS, though some modifications would make it cleaner. We may not care becau=
se the odd heap allocation across asynchronous library interfaces is trivia=
l, and we have worse than that now with synchronising promise/future pairs.=
=C2=A0</span></div></div></blockquote><div><br></div><div>Yes, I think havi=
ng ability to explicitly control where state machine is allocated is a must=
..</div><div><br></div><div>Hmm... You know, I've spent more than 2 deca=
des writing relatively complex multithreaded (occasionally lockless) code a=
nd I never got into future/async paradigm... Never really needed it.</div><=
div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div>A lot of work has gone into this, and while it is not perfect and th=
ere are certainly concerns from some parties with rushing it into the stand=
ard, on balance long years of discussions around similar questions to those=
you are asking have got us to this point.<br></div></div></blockquote><div=
><br></div><div>Well, in this case I am trying to catch up with you. Can=
9;t do it without asking questions.</div><div><br></div><div><br></div><div=
>Regards,</div><div>Michael.</div><div><br></div></div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP5iYbJFx7f%2BoOPkbY%3D8HwtHXr=
pnszfWQmqFGOk_7u-1%3DQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP=
5iYbJFx7f%2BoOPkbY%3D8HwtHXrpnszfWQmqFGOk_7u-1%3DQ%40mail.gmail.com</a>.<br=
/>
--f403045fc1aecbd0750566e15a6c--
.
Author: Todd Fleming <tbfleming@gmail.com>
Date: Thu, 8 Mar 2018 05:43:16 -0800 (PST)
Raw View
------=_Part_2044_1219046448.1520516596446
Content-Type: multipart/alternative;
boundary="----=_Part_2045_1116604585.1520516596446"
------=_Part_2045_1116604585.1520516596446
Content-Type: text/plain; charset="UTF-8"
On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:
>
> I think you (and others) misunderstood my idea -- I do not advocate
> against current proposal, I am aiming only at one aspect of it -- namely
> hiding coroutine behind "plain function" declaration. In my idea compiler
> can generate precisely same language constructs during coroutine
> "instantiation" (as it does in current proposal) -- same Awaitable<T> as
> return types, etc.
>
> And yet it is one of selling points -- unfortunately it requires optional
> compiler optimization, i.e. you can't rely on it. Also, it requires
> compiler to be able to observe coroutine body, which naturally leads to a
> question -- "why hiding it behind 'plain function' facade at all?". Why
> don't we allow user to make related decisions explicitly (like where
> coroutine frame will be allocated).
>
> Current proposal leads to a situation where I can't use coroutine in
> *noexcept* function -- because I can't rely on compiler to use heap
> allocation elision.
>
>
Instead of using templates as an analogy, how about lambda functions?
If lambda functions were like the current stackless coroutine proposal:
- Type erasure would be mandatory, not opt-in.
- Lambda functions would always live on the heap, except when the
optimizer finds a way not to.
If the proposal was more like lambda functions:
- The user could opt into type erasure.
- The coroutine object could live on the stack, or inside another
object, or anywhere else.
Other notes:
- An unwrapped coroutine object probably wouldn't be callable. It may
have an inconvenient interface that's only useful for wrappers to use.
- The current proposal needs changes to std::future; this alternate idea
may need additional changes. Maybe std::promise could do the type erasure
for the async case?
- My initial guess is the object couldn't be copyable or movable; it'd
have to be RVO'ed to its final location.
Todd
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a3a1cd56-29ab-482b-accb-0a0208ef2154%40isocpp.org.
------=_Part_2045_1116604585.1520516596446
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael =
Kilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div class=3D"gmail_quote"><div>I think you (and others) misunderstood my =
idea -- I do not advocate against current proposal, I am aiming only at one=
aspect of it -- namely hiding coroutine behind "plain function" =
declaration. In my idea compiler can generate precisely same language const=
ructs during coroutine "instantiation" (as it does in current pro=
posal) -- same Awaitable<T> as return types, etc.=C2=A0</div></div></=
div></blockquote><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><div class=3D"gmail_quote"><div>And yet=
it is one of selling points -- unfortunately it requires optional compiler=
optimization, i.e. you can't rely on it. Also, it requires compiler to=
be able to observe coroutine body, which naturally leads to a question -- =
"why hiding it behind 'plain function' facade at all?". W=
hy don't we allow user to make related decisions explicitly (like where=
coroutine frame will be allocated).</div><div><br></div><div>Current propo=
sal leads to a situation where I can't use coroutine in <i>noexcept</i>=
function -- because I can't rely on compiler to use heap allocation el=
ision.</div><div><br></div></div></div></blockquote><div>=C2=A0</div><div><=
div>Instead of using templates as an analogy, how about lambda functions?</=
div><div><br></div><div>If lambda functions were like the current stackless=
coroutine proposal:</div><div><ul><li>Type erasure would be mandatory, not=
opt-in.<br></li><li>Lambda functions would always live on the heap, except=
when the optimizer finds a way not to.</li></ul></div><div>If the proposal=
was more like lambda functions:</div><div><ul><li>The user could opt into =
type erasure.<br></li><li>The coroutine object could live on the stack, or =
inside another object, or anywhere else.<br></li></ul></div><div><br></div>=
<div>Other notes:</div><div><ul><li>An unwrapped coroutine object probably =
wouldn't be callable. It may have an inconvenient interface that's =
only useful for wrappers to use.<br></li><li>The current proposal needs cha=
nges to std::future; this alternate idea may need additional changes. Maybe=
std::promise could do the type erasure for the async case?<br></li><li>My =
initial guess is the object couldn't be copyable or movable; it'd h=
ave to be RVO'ed to its final location.</li></ul></div></div><div>Todd<=
/div><div><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/a3a1cd56-29ab-482b-accb-0a0208ef2154%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a3a1cd56-29ab-482b-accb-0a0208ef2154=
%40isocpp.org</a>.<br />
------=_Part_2045_1116604585.1520516596446--
------=_Part_2044_1219046448.1520516596446--
.
Author: Todd Fleming <tbfleming@gmail.com>
Date: Thu, 8 Mar 2018 05:56:40 -0800 (PST)
Raw View
------=_Part_2130_2107174659.1520517400114
Content-Type: multipart/alternative;
boundary="----=_Part_2131_374461581.1520517400114"
------=_Part_2131_374461581.1520517400114
Content-Type: text/plain; charset="UTF-8"
On Thursday, March 8, 2018 at 8:43:16 AM UTC-5, Todd Fleming wrote:
>
> On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:
>>
>> I think you (and others) misunderstood my idea -- I do not advocate
>> against current proposal, I am aiming only at one aspect of it -- namely
>> hiding coroutine behind "plain function" declaration. In my idea compiler
>> can generate precisely same language constructs during coroutine
>> "instantiation" (as it does in current proposal) -- same Awaitable<T> as
>> return types, etc.
>>
>
>
>
>> And yet it is one of selling points -- unfortunately it requires optional
>> compiler optimization, i.e. you can't rely on it. Also, it requires
>> compiler to be able to observe coroutine body, which naturally leads to a
>> question -- "why hiding it behind 'plain function' facade at all?". Why
>> don't we allow user to make related decisions explicitly (like where
>> coroutine frame will be allocated).
>>
>> Current proposal leads to a situation where I can't use coroutine in
>> *noexcept* function -- because I can't rely on compiler to use heap
>> allocation elision.
>>
>>
> Instead of using templates as an analogy, how about lambda functions?
>
> If lambda functions were like the current stackless coroutine proposal:
>
> - Type erasure would be mandatory, not opt-in.
> - Lambda functions would always live on the heap, except when the
> optimizer finds a way not to.
>
> If the proposal was more like lambda functions:
>
> - The user could opt into type erasure.
> - The coroutine object could live on the stack, or inside another
> object, or anywhere else.
>
>
> Other notes:
>
> - An unwrapped coroutine object probably wouldn't be callable. It may
> have an inconvenient interface that's only useful for wrappers to use.
> - The current proposal needs changes to std::future; this alternate
> idea may need additional changes. Maybe std::promise could do the type
> erasure for the async case?
> - My initial guess is the object couldn't be copyable or movable; it'd
> have to be RVO'ed to its final location.
>
> Todd
>
There's a potential problem with doing this inside clang:
- To not be type erased, clang's front end would have to define the
object, since it handles layout issues, sizeof(), and other things.
- The object would contain the optimized state, but the front end can't
predict this.
Todd
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/95e48018-8275-4d99-86f0-940b51e7e8b6%40isocpp.org.
------=_Part_2131_374461581.1520517400114
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, March 8, 2018 at 8:43:16 AM UTC-5, Todd Flemi=
ng wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On W=
ednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote=
"><div>I think you (and others) misunderstood my idea -- I do not advocate =
against current proposal, I am aiming only at one aspect of it -- namely hi=
ding coroutine behind "plain function" declaration. In my idea co=
mpiler can generate precisely same language constructs during coroutine &qu=
ot;instantiation" (as it does in current proposal) -- same Awaitable&l=
t;T> as return types, etc.=C2=A0</div></div></div></blockquote><div><br>=
</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;=
margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr"><div class=3D"gmail_quote"><div>And yet it is one of selling points --=
unfortunately it requires optional compiler optimization, i.e. you can'=
;t rely on it. Also, it requires compiler to be able to observe coroutine b=
ody, which naturally leads to a question -- "why hiding it behind '=
;plain function' facade at all?". Why don't we allow user to m=
ake related decisions explicitly (like where coroutine frame will be alloca=
ted).</div><div><br></div><div>Current proposal leads to a situation where =
I can't use coroutine in <i>noexcept</i> function -- because I can'=
t rely on compiler to use heap allocation elision.</div><div><br></div></di=
v></div></blockquote><div>=C2=A0</div><div><div>Instead of using templates =
as an analogy, how about lambda functions?</div><div><br></div><div>If lamb=
da functions were like the current stackless coroutine proposal:</div><div>=
<ul><li>Type erasure would be mandatory, not opt-in.<br></li><li>Lambda fun=
ctions would always live on the heap, except when the optimizer finds a way=
not to.</li></ul></div><div>If the proposal was more like lambda functions=
:</div><div><ul><li>The user could opt into type erasure.<br></li><li>The c=
oroutine object could live on the stack, or inside another object, or anywh=
ere else.<br></li></ul></div><div><br></div><div>Other notes:</div><div><ul=
><li>An unwrapped coroutine object probably wouldn't be callable. It ma=
y have an inconvenient interface that's only useful for wrappers to use=
..<br></li><li>The current proposal needs changes to std::future; this alter=
nate idea may need additional changes. Maybe std::promise could do the type=
erasure for the async case?<br></li><li>My initial guess is the object cou=
ldn't be copyable or movable; it'd have to be RVO'ed to its fin=
al location.</li></ul></div></div><div>Todd</div></div></blockquote><div><b=
r></div><div>There's a potential problem with doing this inside clang:<=
/div><div><ul><li>To not be type erased, clang's front end would have t=
o define the object, since it handles layout issues, sizeof(), and other th=
ings.<br></li><li>The object would contain the optimized state, but the fro=
nt end can't predict this.<br></li></ul></div><div>Todd</div><div><br><=
/div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/95e48018-8275-4d99-86f0-940b51e7e8b6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/95e48018-8275-4d99-86f0-940b51e7e8b6=
%40isocpp.org</a>.<br />
------=_Part_2131_374461581.1520517400114--
------=_Part_2130_2107174659.1520517400114--
.
Author: inkwizytoryankes@gmail.com
Date: Thu, 8 Mar 2018 06:08:50 -0800 (PST)
Raw View
------=_Part_2064_1584770695.1520518130135
Content-Type: multipart/alternative;
boundary="----=_Part_2065_1061732931.1520518130136"
------=_Part_2065_1061732931.1520518130136
Content-Type: text/plain; charset="UTF-8"
On Thursday, March 8, 2018 at 10:54:24 AM UTC+1, Michael Kilburn wrote:
>
> On Thu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <crusad...@gmail.com
> <javascript:>> wrote:
>
>> i.e. idea is not about coroutine implementation or semantic of generated
>> functions -- it is about having every client to see entire coroutine. At
>> this stage I really don't care exactly how resulting state machine will
>> behave or what methods it will expose.
>>
>
> One more argument -- consider template class and stackless coroutine. Both
> of them are language provided mechanisms for transforming some code into a
> C++ class -- i.e. fundamentally they do the same thing. In case of template
> class there is no way to hide it's declaration from users -- at any point
> entire class definition is visible to every user (even though you may tuck
> away definition of individual member functions into some TU). Stackless
> coroutine (in current form) hides resulting class -- this lack of symmetry
> bothers me. It forces designers to come up with mechanisms designed to
> workaround resulting problems (e.g. heap allocation elision allows us to
> delegate allocation to a party that knows state machine frame size and move
> allocation to stack, if certain criteria are met).
>
>
> Regards,
> Michael.
>
>
>
>
If I understand this problem correctly then we could alter current
proposition to allow optional embedding coroutine state into return object
instead of using allocation.
We then would have 3 kinds: always heap, heap and fixed, only fixed.
Return value will need have something like `std::aligned_storage` with some
arbitrary size. Then if values of coroutine fit this storage then whole
function compile and use this storage for variables, if not and we do not
have enabled option for heap allocation then function fall to compile.
This will have some drawback, one is you will need be careful when you
stack generators you will need calculate size of things used inside (that
are live during `co_yeld`):
generator<int, 30 + sizeof(bar(0))> foo(int i)
{
int j = i;
for (auto k : bar(i)) co_yeld (++j) * k;
}
Another is that return value will be not movable or copyable. Because
otherwise you will need define how it will handle "local variables" when
storage will be copied.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2b313a22-d892-4dbd-8b0a-3d94431b4ee2%40isocpp.org.
------=_Part_2065_1061732931.1520518130136
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, March 8, 2018 at 10:54:24 AM UTC+1, M=
ichael Kilburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote">On Thu, Mar 8, 2018 at 12:15 AM, M=
ichael Kilburn <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"L9ktgQRABAAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">crusad...@gmail.com</a>></span> wrote:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_=
quote"><div>i.e. idea is not about coroutine implementation or semantic of =
generated functions -- it is about having every client to see entire corout=
ine. At this stage I really don't care exactly how resulting state mach=
ine will behave or what methods it will expose.<br></div></div></div></div>=
</blockquote><div><br></div><div>One more argument -- consider template cla=
ss and stackless coroutine. Both of them are language provided mechanisms f=
or transforming some code into a C++ class -- i.e. fundamentally they do th=
e same thing. In case of template class there is no way to hide it's de=
claration from users -- at any point entire class definition is visible to =
every user (even though you may tuck away definition of individual member f=
unctions into some TU). Stackless coroutine (in current form) hides resulti=
ng class -- this lack of symmetry bothers me. It forces designers to come u=
p with mechanisms designed to workaround resulting problems (e.g. heap allo=
cation elision allows us to delegate allocation to a party that knows state=
machine frame size and move allocation to stack, if certain criteria are m=
et).</div><div><br></div><div><br></div><div>Regards,</div><div>Michael.</d=
iv><div><br></div><div><br></div><div><br></div></div></div></div></blockqu=
ote><div>=C2=A0<br>If I understand this problem correctly then we could alt=
er current=20
proposition to allow optional embedding coroutine state into return=20
object instead of using allocation.<br>We then would have 3 kinds: always h=
eap, heap and fixed, only fixed.<br>Return value will need have something l=
ike `std::aligned_storage` with some arbitrary size. Then if values of coro=
utine fit this storage then whole function compile and use this storage for=
variables, if not and we do not have enabled option for heap allocation th=
en function fall to compile.<br><br>This will have some drawback, one is yo=
u will need be careful when you stack generators you will need calculate si=
ze of things used inside (that are live during `co_yeld`):<br><div style=3D=
"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bo=
rder-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"=
prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">generator</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">30</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">+</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">sizeof</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">bar</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
066;" class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">))></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> i</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> j </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> i</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">for</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> k </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> bar</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">i</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">))</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> co_yeld </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(++</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">j</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> k</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span></div></code></div>Another is that return va=
lue will be not movable or copyable. Because otherwise you will need define=
how it will handle "local variables" when storage will be copied=
..<br><br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/2b313a22-d892-4dbd-8b0a-3d94431b4ee2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2b313a22-d892-4dbd-8b0a-3d94431b4ee2=
%40isocpp.org</a>.<br />
------=_Part_2065_1061732931.1520518130136--
------=_Part_2064_1584770695.1520518130135--
.
Author: Lee Howes <xrikcus@gmail.com>
Date: Thu, 8 Mar 2018 08:55:05 -0800
Raw View
--001a11402bbaa2a1110566e98940
Content-Type: text/plain; charset="UTF-8"
> Ultimately, stackless coroutine is a C++ object with methods like
resume()/etc. I don't see why you shouldn't be able to treat it as such --
i.e. storing it as member variable of another class and access in a
virtual function.
Maybe I'm missing something here. You want the compiler to be able to see
the body of the called coroutine, as I understand it. To be clear I am
saying I need to be able to do something like:
class Foo {
virtual Awaitable bar();
};
co_await my_foo->bar();
Now, you also said:
> Nothing prevents you from hiding state machine object (generated from
couroutine declaration) behind a function manually
So I *think* you are saying that you can have a strictly visible coroutine
that you can wrap in an async call to heap allocate it in case you want to
pass the awaitable around, do some bulk collect operation or whatever. Is
that right?
That's a reasonable point of view. At the moment we are pretty happy with
the state of inlining when the functions are visible, and are more
interested in ensuring there are no heap allocations in the example above,
when they are not visible. We really can't afford to significantly increase
the amount of compiler visible code we have, optimising for separate
compilation is really the only option.
> It seems I am missing a lot of background here -- how all these things
are related to fibers or co_await?
It isn't directly, I just wanted to make it clear that your statement
that "having
to propagate 'co_await's down the call tree doesn't seem ideal" is
absolutely not the position my library developers have. It is not universal
- there are many languages in which this approach is a conscious design
choice.
On 8 March 2018 at 06:08, <inkwizytoryankes@gmail.com> wrote:
>
>
> On Thursday, March 8, 2018 at 10:54:24 AM UTC+1, Michael Kilburn wrote:
>>
>> On Thu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <crusad...@gmail.com>
>> wrote:
>>
>>> i.e. idea is not about coroutine implementation or semantic of generated
>>> functions -- it is about having every client to see entire coroutine. At
>>> this stage I really don't care exactly how resulting state machine will
>>> behave or what methods it will expose.
>>>
>>
>> One more argument -- consider template class and stackless coroutine.
>> Both of them are language provided mechanisms for transforming some code
>> into a C++ class -- i.e. fundamentally they do the same thing. In case of
>> template class there is no way to hide it's declaration from users -- at
>> any point entire class definition is visible to every user (even though you
>> may tuck away definition of individual member functions into some TU).
>> Stackless coroutine (in current form) hides resulting class -- this lack of
>> symmetry bothers me. It forces designers to come up with mechanisms
>> designed to workaround resulting problems (e.g. heap allocation elision
>> allows us to delegate allocation to a party that knows state machine frame
>> size and move allocation to stack, if certain criteria are met).
>>
>>
>> Regards,
>> Michael.
>>
>>
>>
>>
> If I understand this problem correctly then we could alter current
> proposition to allow optional embedding coroutine state into return object
> instead of using allocation.
> We then would have 3 kinds: always heap, heap and fixed, only fixed.
> Return value will need have something like `std::aligned_storage` with
> some arbitrary size. Then if values of coroutine fit this storage then
> whole function compile and use this storage for variables, if not and we do
> not have enabled option for heap allocation then function fall to compile.
>
> This will have some drawback, one is you will need be careful when you
> stack generators you will need calculate size of things used inside (that
> are live during `co_yeld`):
> generator<int, 30 + sizeof(bar(0))> foo(int i)
> {
> int j = i;
> for (auto k : bar(i)) co_yeld (++j) * k;
> }
> Another is that return value will be not movable or copyable. Because
> otherwise you will need define how it will handle "local variables" when
> storage will be copied.
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/2b313a22-d892-4dbd-
> 8b0a-3d94431b4ee2%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2b313a22-d892-4dbd-8b0a-3d94431b4ee2%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNUxk8yM0dNqFddMWLQbDe7k%2BBxipCKegB-B2%3DXp12%2B5aA%40mail.gmail.com.
--001a11402bbaa2a1110566e98940
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><span class=3D"gmail-im" style=3D"color:rgb(80,0,80);font-=
family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-lig=
atures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:ini=
tial;text-decoration-color:initial"><div><span style=3D"color:rgb(34,34,34)=
;font-size:12.8px">> Ultimately, stackless coroutine is a C++ object wit=
h methods like resume()/etc. I don't see why you shouldn't be able =
to treat it as such -- i.e. storing it as member variable of another class =
and access in a virtual=C2=A0 function.</span><br></div></span><div style=
=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-=
style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-we=
ight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transf=
orm:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,2=
55);text-decoration-style:initial;text-decoration-color:initial"><br></div>=
<div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12=
..8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norm=
al;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;background-color:rgb=
(255,255,255);text-decoration-style:initial;text-decoration-color:initial">=
Maybe I'm missing something here. You want the compiler to be able to s=
ee the body of the called coroutine, as I understand it. To be clear I am s=
aying I need to be able to do something like:</div><div style=3D"color:rgb(=
34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;f=
ont-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;lette=
r-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decor=
ation-style:initial;text-decoration-color:initial"><br></div><div style=3D"=
color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-styl=
e:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight=
:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:=
none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);=
text-decoration-style:initial;text-decoration-color:initial">class Foo {</d=
iv><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size=
:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initia=
l">=C2=A0 virtual Awaitable bar();</div><div style=3D"color:rgb(34,34,34);f=
ont-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant=
-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:n=
ormal;text-align:start;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style=
:initial;text-decoration-color:initial">};</div><div style=3D"color:rgb(34,=
34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font=
-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-s=
pacing:normal;text-align:start;text-indent:0px;text-transform:none;white-sp=
ace:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decorati=
on-style:initial;text-decoration-color:initial"><br></div><div style=3D"col=
or:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:n=
ormal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:40=
0;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:non=
e;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);tex=
t-decoration-style:initial;text-decoration-color:initial">co_await my_foo-&=
gt;bar();</div><span class=3D"gmail-im" style=3D"color:rgb(80,0,80);font-fa=
mily:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligat=
ures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;=
text-align:start;text-indent:0px;text-transform:none;white-space:normal;wor=
d-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initi=
al;text-decoration-color:initial"><div><br></div></span><div><span class=3D=
"gmail-im" style=3D"color:rgb(80,0,80);font-family:arial,sans-serif;font-si=
ze:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps=
:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:=
0px;text-transform:none;white-space:normal;word-spacing:0px;background-colo=
r:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:init=
ial">Now, you also said:</span></div><div><span class=3D"gmail-im" style=3D=
"color:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;font-styl=
e:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight=
:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:=
none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);=
text-decoration-style:initial;text-decoration-color:initial"><span style=3D=
"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-sty=
le:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weigh=
t:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform=
:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)=
;text-decoration-style:initial;text-decoration-color:initial;float:none;dis=
play:inline">> Nothing prevents you from hiding state machine object (ge=
nerated from couroutine declaration) behind a function manually</span><br><=
/span></div><div><br></div><div>So I *think* you are saying that you can ha=
ve a strictly visible coroutine that you can wrap in an async call to heap =
allocate it in case you want to pass the awaitable around, do some bulk col=
lect operation or whatever. Is that right?</div><div><br></div><div>That=
9;s a reasonable point of view. At the moment we are pretty happy with the =
state of inlining when the functions are visible, and are more interested i=
n ensuring there are no heap allocations in the example above, when they ar=
e not visible. We really can't afford to significantly increase the amo=
unt of compiler visible code we have, optimising for separate compilation i=
s really the only option.</div><div><span class=3D"gmail-im" style=3D"color=
:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;font-style:norm=
al;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;l=
etter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;w=
hite-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-d=
ecoration-style:initial;text-decoration-color:initial"><br></span></div><di=
v><span class=3D"gmail-im" style=3D"color:rgb(80,0,80);font-family:arial,sa=
ns-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;f=
ont-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:st=
art;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px=
;background-color:rgb(255,255,255);text-decoration-style:initial;text-decor=
ation-color:initial">>=C2=A0<span style=3D"color:rgb(34,34,34);font-fami=
ly:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatur=
es:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;te=
xt-align:start;text-indent:0px;text-transform:none;white-space:normal;word-=
spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial=
;text-decoration-color:initial;float:none;display:inline">It seems I am mis=
sing a lot of background here -- how all these things are related to fibers=
or co_await?</span></span></div><div><span class=3D"gmail-im" style=3D"fon=
t-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-l=
igatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:i=
nitial;text-decoration-color:initial"><br></span></div><div><span class=3D"=
gmail-im" style=3D"font-family:arial,sans-serif;font-size:12.8px;font-style=
:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:=
400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);t=
ext-decoration-style:initial;text-decoration-color:initial">It isn't di=
rectly, I just wanted to make it clear that your statement that=C2=A0<span =
style=3D"color:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;f=
ont-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;fon=
t-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tr=
ansform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,2=
55,255);text-decoration-style:initial;text-decoration-color:initial;float:n=
one;display:inline">"</span><span style=3D"color:rgb(80,0,80);font-fam=
ily:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatu=
res:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;t=
ext-align:start;text-indent:0px;text-transform:none;white-space:normal;word=
-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initia=
l;text-decoration-color:initial">having to propagate 'co_await's do=
wn the call tree doesn't seem ideal" is absolutely not the positio=
n my library developers have. It is not universal - there are many language=
s in which this approach is a conscious design choice.</span></span></div><=
/div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On 8 March 2=
018 at 06:08, <span dir=3D"ltr"><<a href=3D"mailto:inkwizytoryankes@gma=
il.com" target=3D"_blank">inkwizytoryankes@gmail.com</a>></span> wrote:<=
br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><br>On Thursday, Mar=
ch 8, 2018 at 10:54:24 AM UTC+1, Michael Kilburn wrote:<span class=3D""><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gm=
ail_quote">On Thu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <span dir=3D"lt=
r"><<a rel=3D"nofollow">crusad...@gmail.com</a>></span> wrote:<br><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div>i.e. idea is not about coroutine implementation or semantic of gener=
ated functions -- it is about having every client to see entire coroutine. =
At this stage I really don't care exactly how resulting state machine w=
ill behave or what methods it will expose.<br></div></div></div></div></blo=
ckquote><div><br></div><div>One more argument -- consider template class an=
d stackless coroutine. Both of them are language provided mechanisms for tr=
ansforming some code into a C++ class -- i.e. fundamentally they do the sam=
e thing. In case of template class there is no way to hide it's declara=
tion from users -- at any point entire class definition is visible to every=
user (even though you may tuck away definition of individual member functi=
ons into some TU). Stackless coroutine (in current form) hides resulting cl=
ass -- this lack of symmetry bothers me. It forces designers to come up wit=
h mechanisms designed to workaround resulting problems (e.g. heap allocatio=
n elision allows us to delegate allocation to a party that knows state mach=
ine frame size and move allocation to stack, if certain criteria are met).<=
/div><div><br></div><div><br></div><div>Regards,</div><div>Michael.</div><d=
iv><br></div><div><br></div><div><br></div></div></div></div></blockquote><=
/span><div>=C2=A0<br>If I understand this problem correctly then we could a=
lter current=20
proposition to allow optional embedding coroutine state into return=20
object instead of using allocation.<br>We then would have 3 kinds: always h=
eap, heap and fixed, only fixed.<br>Return value will need have something l=
ike `std::aligned_storage` with some arbitrary size. Then if values of coro=
utine fit this storage then whole function compile and use this storage for=
variables, if not and we do not have enabled option for heap allocation th=
en function fall to compile.<br><br>This will have some drawback, one is yo=
u will need be careful when you stack generators you will need calculate si=
ze of things used inside (that are live during `co_yeld`):<br><div style=3D=
"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-sty=
le:solid;border-width:1px" class=3D"m_4087594380049096864prettyprint"><code=
class=3D"m_4087594380049096864prettyprint"><div class=3D"m_408759438004909=
6864subprettyprint"><span style=3D"color:#000" class=3D"m_40875943800490968=
64styled-by-prettify">generator</span><span style=3D"color:#660" class=3D"m=
_4087594380049096864styled-by-prettify"><</span><span style=3D"color:#00=
8" class=3D"m_4087594380049096864styled-by-prettify">int</span><span style=
=3D"color:#660" class=3D"m_4087594380049096864styled-by-prettify">,</span><=
span style=3D"color:#000" class=3D"m_4087594380049096864styled-by-prettify"=
> </span><span style=3D"color:#066" class=3D"m_4087594380049096864styled-by=
-prettify">30</span><span style=3D"color:#000" class=3D"m_40875943800490968=
64styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_4087594=
380049096864styled-by-prettify">+</span><span style=3D"color:#000" class=3D=
"m_4087594380049096864styled-by-prettify"> </span><span style=3D"color:#008=
" class=3D"m_4087594380049096864styled-by-prettify">sizeof</span><span styl=
e=3D"color:#660" class=3D"m_4087594380049096864styled-by-prettify">(</span>=
<span style=3D"color:#000" class=3D"m_4087594380049096864styled-by-prettify=
">bar</span><span style=3D"color:#660" class=3D"m_4087594380049096864styled=
-by-prettify">(</span><span style=3D"color:#066" class=3D"m_408759438004909=
6864styled-by-prettify">0</span><span style=3D"color:#660" class=3D"m_40875=
94380049096864styled-by-prettify">))></span><span style=3D"color:#000" c=
lass=3D"m_4087594380049096864styled-by-prettify"> foo</span><span style=3D"=
color:#660" class=3D"m_4087594380049096864styled-by-prettify">(</span><span=
style=3D"color:#008" class=3D"m_4087594380049096864styled-by-prettify">int=
</span><span style=3D"color:#000" class=3D"m_4087594380049096864styled-by-p=
rettify"> i</span><span style=3D"color:#660" class=3D"m_4087594380049096864=
styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_408759438=
0049096864styled-by-prettify"><br></span><span style=3D"color:#660" class=
=3D"m_4087594380049096864styled-by-prettify">{</span><span style=3D"color:#=
000" class=3D"m_4087594380049096864styled-by-prettify"><br>=C2=A0 =C2=A0 </=
span><span style=3D"color:#008" class=3D"m_4087594380049096864styled-by-pre=
ttify">int</span><span style=3D"color:#000" class=3D"m_4087594380049096864s=
tyled-by-prettify"> j </span><span style=3D"color:#660" class=3D"m_40875943=
80049096864styled-by-prettify">=3D</span><span style=3D"color:#000" class=
=3D"m_4087594380049096864styled-by-prettify"> i</span><span style=3D"color:=
#660" class=3D"m_4087594380049096864styled-by-prettify">;</span><span style=
=3D"color:#000" class=3D"m_4087594380049096864styled-by-prettify"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_4087594380049096864=
styled-by-prettify">for</span><span style=3D"color:#000" class=3D"m_4087594=
380049096864styled-by-prettify"> </span><span style=3D"color:#660" class=3D=
"m_4087594380049096864styled-by-prettify">(</span><span style=3D"color:#008=
" class=3D"m_4087594380049096864styled-by-prettify">auto</span><span style=
=3D"color:#000" class=3D"m_4087594380049096864styled-by-prettify"> k </span=
><span style=3D"color:#660" class=3D"m_4087594380049096864styled-by-prettif=
y">:</span><span style=3D"color:#000" class=3D"m_4087594380049096864styled-=
by-prettify"> bar</span><span style=3D"color:#660" class=3D"m_4087594380049=
096864styled-by-prettify">(</span><span style=3D"color:#000" class=3D"m_408=
7594380049096864styled-by-prettify">i</span><span style=3D"color:#660" clas=
s=3D"m_4087594380049096864styled-by-prettify">))</span><span style=3D"color=
:#000" class=3D"m_4087594380049096864styled-by-prettify"> co_yeld </span><s=
pan style=3D"color:#660" class=3D"m_4087594380049096864styled-by-prettify">=
(++</span><span style=3D"color:#000" class=3D"m_4087594380049096864styled-b=
y-prettify">j</span><span style=3D"color:#660" class=3D"m_40875943800490968=
64styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_4087594=
380049096864styled-by-prettify"> </span><span style=3D"color:#660" class=3D=
"m_4087594380049096864styled-by-prettify">*</span><span style=3D"color:#000=
" class=3D"m_4087594380049096864styled-by-prettify"> k</span><span style=3D=
"color:#660" class=3D"m_4087594380049096864styled-by-prettify">;</span><spa=
n style=3D"color:#000" class=3D"m_4087594380049096864styled-by-prettify"><b=
r></span><span style=3D"color:#660" class=3D"m_4087594380049096864styled-by=
-prettify">}</span><span style=3D"color:#000" class=3D"m_408759438004909686=
4styled-by-prettify"><br></span></div></code></div>Another is that return v=
alue will be not movable or copyable. Because otherwise you will need defin=
e how it will handle "local variables" when storage will be copie=
d.<br><br></div></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/2b313a22-d892-4dbd-8b0a-3d94431b4ee2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/2b31=
3a22-d892-4dbd-<wbr>8b0a-3d94431b4ee2%40isocpp.org</a><wbr>.<br>
</blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAJH_FNUxk8yM0dNqFddMWLQbDe7k%2BBxipC=
KegB-B2%3DXp12%2B5aA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNUxk8=
yM0dNqFddMWLQbDe7k%2BBxipCKegB-B2%3DXp12%2B5aA%40mail.gmail.com</a>.<br />
--001a11402bbaa2a1110566e98940--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 8 Mar 2018 09:12:14 -0800 (PST)
Raw View
------=_Part_2643_803238070.1520529134235
Content-Type: multipart/alternative;
boundary="----=_Part_2644_1571508969.1520529134237"
------=_Part_2644_1571508969.1520529134237
Content-Type: text/plain; charset="UTF-8"
On Thursday, March 8, 2018 at 1:15:38 AM UTC-5, Michael Kilburn wrote:
>
> On Wed, Mar 7, 2018 at 9:33 PM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:
>>>
>>> I think you (and others) misunderstood my idea -- I do not advocate
>>> against current proposal, I am aiming only at one aspect of it -- namely
>>> hiding coroutine behind "plain function" declaration.
>>>
>>
>> But that's practically the point of the Coroutines TS design: that the
>> compiler generates the coroutine machinery based entirely on what is going
>> on inside of the function, not how the outside world uses it. And as will
>> be discussed below, the ramifications of changing "only one aspect of it"
>> fundamentally changes the nature of what you're talking about.
>>
>
> I am sticking to my guns (i.e. going to claim I am being
> misunderstood).I'll try to explain it again:
>
- stackless coroutines is when your code gets transformed int a C++ object
> which represents a state machine (and associated fluff to tie it with the
> rest of your code)
> - the idea is to use template-like approach to "transformation" step -- as
> far as I am concerned it could generate exactly the same declarations as
> you write in MSVC version that supports Gor's proposal. I.e.
>
You are not being misunderstood. You're trying to equate all "stackless
coroutine" proposals; you're claiming that they're all just minor
variations of the same concept.
*They are not*. Coroutines TS is not just creating a resumable function;
it's a lot more than that. It's implementing a specific model of
coroutines, which is different from the model you're defining.
If you want "just resumable functions", then you need to understand that
this really is a completely different proposal with a completely different
design from the Coroutines TS. It's not a slight modification of Coroutines
TS (which is evidence in the fact that your design literally removes all of
the Coroutines TS's keywords).
Your design is a suspend-down coroutine model. When your kind of coroutine
yields, it always returns to its nearest non-coroutine caller, who is
responsible for scheduling its resumption at some point. Coroutines TS is a
suspend-up coroutine model: the code responsible for scheduling its
resumption is the code *inside* the coroutine, not necessarily its caller.
If the code inside the coroutine suspends to the caller, that's because the
particular coroutine chooses to.
Generators are the classic case of suspend-down. That's why your design
works especially well with them, and why the Coroutines TS works so poorly
with them. Continuations however are a classic case of suspend-up. This is
why your design requires lots of extra work to use them, while the
Coroutines TS makes it look like synchronous code.
Coroutines TS will never be as good at generators as your idea is. But
neither will your idea be as good at asynchronous code transformations as
the Coroutines TS is.
But the difference is that all translation units will see everything,
> unlike current state where (typically) only one will have a full vision.
> This would allow every call site to know everything about generated state
> machine (e.g. it's size). This will allow certain features:
> - caller can explicitly control location of coroutine frame
> - a coroutine will be clearly different from a function -- which would
> allow to avoid necessity of co_await or co_return.
>
No, you still need `co_await` and such (or something of a similar nature),
because not all asychronous functions should have to be visible. So you
still need to be able to suspend your function and schedule its resumption
based on the return value from some other function.
The way the resumable expressions system handled this was to force you to
do what the Coroutines TS effectively does when you invoke `co_await` and
such: manually wrap your resumable function in a hidden lambda that stores
a promise type and returns a future hooked into it.
The *entire point* of the Coroutines TS is to keep you from having to write
such boilerplate. Every design decision is based on that.
Compiler can see that current coroutine calls another coroutine and
> generate required fluff automatically. You can introduce a new keyword (or
> convention) that will allow you to call coroutine in other way (but I doubt
> this need will be great).
> - inlining of some of generated C++ object methods
>
Inlining is only relevant when dealing with suspend-down style coroutines.
That is, generators and the like. Inlining is not relevant (or possible)
when dealing with suspend-up continuations. This is why such inlining is an
optimization to Coroutines TS rather than a requirement. It's a suspend-up
model, so it does things in a suspend-up way.
- you need to update only one portion of compiler -- one that transforms
> coroutine declarations into state machine class declaration. No need to
> introduce additional logic in other areas.
> - etc
>
> i.e. idea is not about coroutine implementation or semantic of generated
> functions -- it is about having every client to see entire coroutine. At
> this stage I really don't care exactly how resulting state machine will
> behave or what methods it will expose.
>
> You broke the rules. You didn't invoke `std::async`; you made a new
>> function. Under this design, any asynchronous library will have to have
>> `coro_` versions of all of its asynchronous functions, rather than just
>> using `future`s or similar such types that allow you to apply continuations
>> to them.
>>
>
> I see... one of the aims is to integrate coroutines with future/async
> stuff... I am probably behind on all this. All async libs I looked at used
> same approach -- public API consists of a function (async_foo) that takes a
> callback. Then someone somewhere cranks the event loop which eventually
> calls "process_events()" library function that in turn calls aforementioned
> callback.
>
> So, for this library to add coroutine support you'd have to create second
> inline function (or macro) coro_foo() that takes address of resume() method
> of current coroutine, registers it using async_foo() and suspends current
> coroutine. I.e. in this design you still have to add second version of your
> async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fault is this
> approach -- everything is clear and clean.
>
> Now, if library instead exports "future<int> foo()" -- there is no need
> for coro_foo(), but implementation becomes less efficient and more complex.
> Because of type erasures, having to allocate memory, having to move values
> and other stuff (like synchronization). Am I right? Is it a good price for
> not having to add a (rather simple) coro_foo()?
>
It all depends: is the person calling the async routine the one who
actually has the continuation? The `future.then`-style interface allows
anyone at any time to hook a continuation into the process. Your `coro_foo`
style requires that the exact caller be the one who provides the
continuation.
And what if the continuation function itself needs a continuation? The
caller has to provide that too. And what if the inner continuation needs to
access something from the outer continuation? Well, you have to allocate
that explicitly. And so forth.
`co_await`-style coding handles this with no manual intervention. Herb
Sutter made a great presentation
<https://channel9.msdn.com/events/Build/2013/2-306> a while back (skip
ahead to around 51 minutes) on the failings of explicit callback-style
continuations through lambdas and such, and demonstrated how use of `await`
can make asynchronous code look exactly like synchronous code.
I'll reproduce his example here, in case you're unwilling to watch the
video.
Here's the synchronous code. It reads from a given filename, appending
`suffix` to each "chunk" in the file. It's based on one of Microsoft's
asynchronous file IO APIs (note that I've slightly adjusted some of the
code):
string read(string filename, string suffix)
{
istream fi = open(filename).get();
string ret, chunk;
while((chunk = fi.read().get()).size())
ret += chunk + suffix;
return ret;
}
All of the `.get()` calls are there to convert asynchronous tasks into
synchronous operations. Our goal is to take this code and make it
asynchronous to the caller.
That `while` loop is the pernicious part. You have to invoke `fi.read()`,
but then you have to provide a continuation function to it. That
continuation function must provoke additional `fi.read()` calls as needed.
And each of those calls must pass a continuation function. Namely *itself*.
That pretty much requires heap allocation, lambdas, and heap allocation of
lambdas. Nobody wants to write that code, and nobody wants to debug it.
The Coroutines TS equivalent would look like this:
task<string> read(string filename, string suffix)
{
istream fi = co_await open(filename);
string ret, chunk;
while((chunk = co_await fi.read()).size())
ret += chunk + suffix;
return ret;
}
You *cannot* get code that is simpler than that. And your `coro_func`
version would not work, due to the need of this code to continue itself.
You'd have to write a lambda, heap-allocate it, and do a bunch of other
stuff to make the explicit continuation code work.
Coroutines TS exists to make that explicit work unnecessary.
The kind of design you've presented is exactly what the resumable
>> expressions proposal used
>> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>. Only
>> it was a bit cleverer about it, such that you would just have a resumable
>> function called "await" that could be overloaded for some "awaitable" type,
>> which would do the scheduling and unpacking, returning the unpacked value
>> once resumed.
>>
>
>> You really should look at that proposal; it's clearly what you want. And
>> yes, it was looked at, but it didn't move forward past P0114R0.
>>
>
> Thank you, I will read it. But as I said -- it isn't what I was talking
> about.
>
How can you say it isn't what you were talking about when you *haven't read
it*? It is essentially your design, only more fully fleshed out. Like your
design, it marks coroutine functions. Unlike your design, it recognizes
that within a coroutine, you might want to call a coroutine that suspends
to you rather than to your caller, so it has syntax for that. Coroutines
have to be defined inline, just like your design. And so forth.
And it has all of the downsides of your proposal. `co_await`-style
continuations are harder to use, requiring explicit coding of wrappers and
the like.
I am probably not the best communicator.
>
> In any case -- I am not insisting that this is a brilliant idea that will
> turn the world on it's head. Just asking for opinions and if it was already
> considered.
>
And as previously stated, a design almost identical to yours was
considered. As far as I can tell, it wasn't "rejected" so much as the
people behind it stopped working on it. They took the paper design as far
as they could, but implementing it would require a great deal of time and
effort. Gor and Microsoft were willing/able to put that time and effort in;
the people behind the resumable expressions proposal weren't.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/5a1e0d6f-286a-4c61-8746-e7baae61c94f%40isocpp.org.
------=_Part_2644_1571508969.1520529134237
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, March 8, 2018 at 1:15:38 AM UTC-5, Michael Ki=
lburn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div><div class=3D"gmail_quote">On Wed, Mar 7, 2018 at 9:33 PM, Nicol Bolas =
<span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfusca=
ted-mailto=3D"i8RkbRQ0BAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
9;javascript:';return true;" onclick=3D"this.href=3D'javascript:=
9;;return true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr">On Wednesday, March 7, 2018 at 10:07:37 PM=
UTC-5, Michael Kilburn wrote:<span><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div class=3D"gmail_quote">I think you (and others) misun=
derstood my idea -- I do not advocate against current proposal, I am aiming=
only at one aspect of it -- namely hiding coroutine behind "plain fun=
ction" declaration.<br></div></div></blockquote></span></div></blockqu=
ote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br>But that's=
practically the point of the Coroutines TS design: that the compiler gener=
ates the coroutine machinery based entirely on what is going on inside of t=
he function, not how the outside world uses it. And as will be discussed be=
low, the ramifications of changing "only one aspect of it" fundam=
entally changes the nature of what you're talking about.<br></div></div=
></blockquote><div><br></div><div>I am sticking to my guns (i.e. going to c=
laim I am being misunderstood).I'll try to explain it again:</div></div=
></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
dir=3D"ltr"><div><div class=3D"gmail_quote"><div>- stackless coroutines is=
when your code gets transformed int a C++ object which represents a state =
machine (and associated fluff to tie it with the rest of your code)</div><d=
iv>- the idea is to use template-like approach to "transformation"=
; step -- as far as I am concerned it could generate exactly the same decla=
rations as you write in MSVC version that supports Gor's proposal. I.e.=
</div></div></div></div></blockquote><div><br>You are not being misundersto=
od. You're trying to equate all "stackless=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br><br><i>They are not</i>. Coroutines =
TS is not just creating a resumable function; it's a lot more than that=
.. It's implementing a specific model of coroutines, which is different =
from the model you're defining.<br><br>If you want "just resumable=
functions", then you need to understand that this really is a complet=
ely different proposal with a completely different design from the Coroutin=
es TS. It's not a slight modification of Coroutines TS (which is eviden=
ce in the fact that your design literally removes all of the Coroutines TS&=
#39;s keywords).<br><br>Your design is a=20
suspend-down coroutine model. When your kind of coroutine yields, it always=
returns
to its nearest non-coroutine caller, who is responsible for scheduling its=
=20
resumption at some point. Coroutines TS is a suspend-up coroutine model:
the code responsible for scheduling its resumption is the code <i>inside</=
i> the coroutine, not necessarily its caller. If the code inside the corout=
ine suspends to the caller, that's because the particular coroutine cho=
oses to.<br><br>Generators
are the classic case of suspend-down. That's why your design works=20
especially well with them, and why the Coroutines TS works so poorly with=
=20
them. Continuations however are a classic case of suspend-up. This is=20
why your design requires lots of extra work to use them, while the=20
Coroutines TS makes it look like synchronous code.<br><br>Coroutines TS wil=
l never be as good at generators as your idea is. But neither will your ide=
a be as good at asynchronous code transformations as the Coroutines TS is.<=
br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div></div><div>But the difference is that =
all translation units will see everything, unlike current state where (typi=
cally) only one will have a full vision. This would allow every call site t=
o know everything about generated state machine (e.g. it's size). This =
will allow certain features:</div><div>- caller can explicitly control loca=
tion of coroutine frame</div><div>- a coroutine will be clearly different f=
rom a function -- which would allow to avoid necessity of co_await or co_re=
turn.</div></div></div></div></blockquote><div><br>No, you still need `co_a=
wait` and such (or something of a similar nature), because not all asychron=
ous functions should have to be visible. So you still need to be able to su=
spend your function and schedule its resumption based on the return value f=
rom some other function.<br><br>The way the resumable expressions system ha=
ndled this was to force you to do what the Coroutines TS effectively does w=
hen you invoke `co_await` and such: manually wrap your resumable function i=
n a hidden lambda that stores a promise type and returns a future hooked in=
to it.<br><br>The <i>entire point</i> of the Coroutines TS is to keep you f=
rom having to write such boilerplate. Every design decision is based on tha=
t.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><div>Compiler can see that current corou=
tine calls another coroutine and generate required fluff automatically. You=
can introduce a new keyword (or convention) that will allow you to call co=
routine in other way (but I doubt this need will be great).</div><div>- inl=
ining of some of generated C++ object methods</div></div></div></div></bloc=
kquote><div><br>Inlining is only relevant when dealing with suspend-down st=
yle coroutines. That is, generators and the like. Inlining is not relevant =
(or possible) when dealing with suspend-up continuations. This is why such =
inlining is an optimization to Coroutines TS rather than a requirement. It&=
#39;s a suspend-up model, so it does things in a suspend-up way.<br><br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div =
class=3D"gmail_quote"><div>- you need to update only one portion of compile=
r -- one that transforms coroutine declarations into state machine class de=
claration. No need to introduce additional logic in other areas.</div><div>=
- etc<br></div><div><br></div><div>i.e. idea is not about coroutine impleme=
ntation or semantic of generated functions -- it is about having every clie=
nt to see entire coroutine. At this stage I really don't care exactly h=
ow resulting state machine will behave or what methods it will expose.</div=
><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><span><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div dir=3D=
"ltr"><span><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>You broke=
the rules. You didn't invoke `std::async`; you made a new function. Un=
der this design, any asynchronous library will have to have `coro_` version=
s of all of its asynchronous functions, rather than just using `future`s or=
similar such types that allow you to apply continuations to them.<br></div=
></div></div></div></span></div></div></div></div></span></div></blockquote=
><div><br></div><div>I see... one of the aims is to integrate coroutines wi=
th future/async stuff... I am probably behind on all this. All async libs I=
looked at used same approach -- public API consists of a function (async_f=
oo) that takes a callback. Then someone somewhere cranks the event loop whi=
ch eventually calls "process_events()" library function that in t=
urn calls aforementioned callback.</div><div><br></div><div>So, for this li=
brary to add coroutine support you'd have to create second inline funct=
ion (or macro) coro_foo() that takes address of resume() method of current =
coroutine, registers it using async_foo() and suspends current coroutine. I=
..e. in this design you still have to add second version of your async_foo()=
-- a coroutine-aware wrapper coro_foo(). I see no fault is this approach -=
- everything is clear and clean.</div><div><br></div><div>Now, if library i=
nstead exports "future<int> foo()" -- there is no need for =
coro_foo(), but implementation becomes less efficient and more complex. Bec=
ause of type erasures, having to allocate memory, having to move values and=
other stuff (like synchronization). Am I right? Is it a good price for not=
having to add a (rather simple) coro_foo()?</div></div></div></div></block=
quote><div><br>It all depends: is the person calling the async routine the =
one who actually has the continuation? The `future.then`-style interface al=
lows anyone at any time to hook a continuation into the process. Your `coro=
_foo` style requires that the exact caller be the one who provides the cont=
inuation.<br><br>And what if the continuation function itself needs a conti=
nuation? The caller has to provide that too. And what if the inner continua=
tion needs to access something from the outer continuation? Well, you have =
to allocate that explicitly. And so forth.<br><br>`co_await`-style coding h=
andles this with no manual intervention. Herb Sutter made a <a href=3D"http=
s://channel9.msdn.com/events/Build/2013/2-306">great presentation</a> a whi=
le back (skip ahead to around 51 minutes) on the failings of explicit callb=
ack-style continuations through lambdas and such, and demonstrated how use =
of `await` can make asynchronous code look exactly like synchronous code.<b=
r><br>I'll reproduce his example here, in case you're unwilling to =
watch the video.<br><br>Here's the synchronous code. It reads from a gi=
ven filename, appending `suffix` to each "chunk" in the file. It&=
#39;s based on one of Microsoft's asynchronous file IO APIs (note that =
I've slightly adjusted some of the code):<br><br><div style=3D"backgrou=
nd-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-styl=
e: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettypri=
nt"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> read</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">string</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> filename</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> suffix</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 istream </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">fi</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> open</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">filename</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">).</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">get</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">st=
ring</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ret</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> chunk</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">while</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">((</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">chunk </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">fi</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">read</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">().</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">get</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()).</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">size</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">())</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 ret </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">+=3D</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> chunk </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> suffix</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> ret</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span>=
</div></code></div><br>All of the `.get()` calls are there to convert async=
hronous tasks into synchronous operations. Our goal is to take this code an=
d make it asynchronous to the caller.<br><br>That `while` loop is the perni=
cious part. You have to invoke `fi.read()`, but then you have to provide a =
continuation function to it. That continuation function must provoke additi=
onal `fi.read()` calls as needed. And each of those calls must pass a conti=
nuation function. Namely <i>itself</i>. That pretty much requires heap allo=
cation, lambdas, and heap allocation of lambdas. Nobody wants to write that=
code, and nobody wants to debug it.<br><br>The Coroutines TS equivalent wo=
uld look like this:<br><br><div style=3D"background-color: rgb(250, 250, 25=
0); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1p=
x; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyp=
rint"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">task</span><span style=3D"color: #080;" class=3D"styled-=
by-prettify"><string></span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> read</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
filename</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> suffix</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 istream </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">fi</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> co_await open</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">filename</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">str=
ing</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ret</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> chunk</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">while</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">((</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">chunk </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> co_await </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">fi</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
read</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()).</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">size</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">())</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 ret </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">+=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> chunk </span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">+</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> suffix</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> ret</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span></div></code></div><br>You <i>cannot</i> get code that =
is simpler than that. And your `coro_func` version would not work, due to t=
he need of this code to continue itself. You'd have to write a lambda, =
heap-allocate it, and do a bunch of other stuff to make the explicit contin=
uation code work.<br><br>Coroutines TS exists to make that explicit work un=
necessary.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div></div><div></div=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The kind of design yo=
u've presented is <a href=3D"http://open-std.org/JTC1/SC22/WG21/docs/pa=
pers/2015/p0114r0.pdf" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"th=
is.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fopen-std.org%2FJ=
TC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0114r0.pdf\x26sa\x3dD\x26sntz\x=
3d1\x26usg\x3dAFQjCNHiqyTXibcdjweNAkVM9dxtpcUC3g';return true;" onclick=
=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fopen-std.o=
rg%2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0114r0.pdf\x26sa\x3dD\x26=
sntz\x3d1\x26usg\x3dAFQjCNHiqyTXibcdjweNAkVM9dxtpcUC3g';return true;">e=
xactly what the resumable expressions proposal used</a>. Only it was a bit =
cleverer about it, such that you would just have a resumable function calle=
d "await" that could be overloaded for some "awaitable"=
type, which would do the scheduling and unpacking, returning the unpacked =
value once resumed.=C2=A0</div></div></blockquote><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div><br>You really should look at that proposal; it=
's clearly what you want. And yes, it was looked at, but it didn't =
move forward past P0114R0.</div></div></blockquote><div><br></div><div>Than=
k you, I will read it. But as I said -- it isn't what I was talking abo=
ut.</div></div></div></div></blockquote><div><br>How can you say it isn'=
;t what you were talking about when you <i>haven't read it</i>? It is e=
ssentially your design, only more fully fleshed out. Like your design, it m=
arks coroutine functions. Unlike your design, it recognizes that within a c=
oroutine, you might want to call a coroutine that suspends to you rather th=
an to your caller, so it has syntax for that. Coroutines have to be defined=
inline, just like your design. And so forth.<br><br>And it has all of the =
downsides of your proposal. `co_await`-style continuations are harder to us=
e, requiring explicit coding of wrappers and the like.<br><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote"><div>I am probably not the best communicator.<br></div><div><br=
></div><div>In any case -- I am not insisting that this is a brilliant idea=
that will turn the world on it's head. Just asking for opinions and if=
it was already considered.</div></div></div></div></blockquote><div><br>An=
d as previously stated, a design almost identical to yours was considered. =
As far as I can tell, it wasn't "rejected" so much as the peo=
ple behind it stopped working on it. They took the paper design as far as t=
hey could, but implementing it would require a great deal of time and effor=
t. Gor and Microsoft were willing/able to put that time and effort in; the =
people behind the resumable expressions proposal weren't.<br></div></di=
v>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/5a1e0d6f-286a-4c61-8746-e7baae61c94f%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5a1e0d6f-286a-4c61-8746-e7baae61c94f=
%40isocpp.org</a>.<br />
------=_Part_2644_1571508969.1520529134237--
------=_Part_2643_803238070.1520529134235--
.
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Thu, 8 Mar 2018 15:04:13 -0800 (PST)
Raw View
------=_Part_3575_1685621849.1520550253461
Content-Type: multipart/alternative;
boundary="----=_Part_3576_1991041374.1520550253462"
------=_Part_3576_1991041374.1520550253462
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Thursday, March 8, 2018 at 9:12:14 AM UTC-8, Nicol Bolas wrote:
>
> [...]
> The way the resumable expressions system handled this was to force you to=
=20
> do what the Coroutines TS effectively does when you invoke `co_await` and=
=20
> such: manually wrap your resumable function in a hidden lambda that store=
s=20
> a promise type and returns a future hooked into it.
>
> The *entire point* of the Coroutines TS is to keep you from having to=20
> write such boilerplate. Every design decision is based on that.
> [...]
> `co_await`-style coding handles this with no manual intervention. Herb=20
> Sutter made a great presentation=20
> <https://channel9.msdn.com/events/Build/2013/2-306> a while back (skip=20
> ahead to around 51 minutes) on the failings of explicit callback-style=20
> continuations through lambdas and such, and demonstrated how use of `awai=
t`=20
> can make asynchronous code look exactly like synchronous code.
>
> I'll reproduce his example here, in case you're unwilling to watch the=20
> video.
>
> Here's the synchronous code. It reads from a given filename, appending=20
> `suffix` to each "chunk" in the file. It's based on one of Microsoft's=20
> asynchronous file IO APIs (note that I've slightly adjusted some of the=
=20
> code):
>
> string read(string filename, string suffix)
> {
> istream fi =3D open(filename).get();
> string ret, chunk;
> while((chunk =3D fi.read().get()).size())
> ret +=3D chunk + suffix;
>
> return ret;
> }
>
> All of the `.get()` calls are there to convert asynchronous tasks into=20
> synchronous operations. Our goal is to take this code and make it=20
> asynchronous to the caller.
>
> That `while` loop is the pernicious part. You have to invoke `fi.read()`,=
=20
> but then you have to provide a continuation function to it. That=20
> continuation function must provoke additional `fi.read()` calls as needed=
..=20
> And each of those calls must pass a continuation function. Namely *itself=
*.=20
> That pretty much requires heap allocation, lambdas, and heap allocation o=
f=20
> lambdas. Nobody wants to write that code, and nobody wants to debug it.
>
> The Coroutines TS equivalent would look like this:
>
> task<string> read(string filename, string suffix)
> {
> istream fi =3D co_await open(filename);
> string ret, chunk;
> while((chunk =3D co_await fi.read()).size())
> ret +=3D chunk + suffix;
>
> return ret;
> }
>
> You *cannot* get code that is simpler than that.
>
IMHO, this is a good example of a problem that is hard with futures and=20
easier with co_foo syntax.
For the record, let me tackle your original example,
std::future<int> async_call(...) {
auto val =3D co_await std::async(some_function, ...);
co_return val + 1;
}
This one is easy to do with something like Boost.Future. With my own toy=20
futures library=20
<https://github.com/Quuxplusone/toy-dns/blob/bus/src/include/nonstd-future.=
h#L6>,=20
it looks like this:
nonstd::future<int> async_call(...) {
return nonstd::async(some_function, ...)
.on_value([](auto val) { return val + 1; });
}
I even find this future-based version easier to understand (at the moment):=
=20
I find it easier to trace the exceptional control flow "past" the on_value=
=20
call, and just say "aha, if the future was not satisfied with a value, then=
=20
we'll propagate the exception." With the co_foo-based version, IIUC, you=
=20
have to remember that every "co_await" includes an implicit "co_throw", so=
=20
that the operand of the "co_return" statement will not be evaluated if=20
some_function throws. (But most likely this is exactly as obvious in=20
hindsight as the idea of exceptional codepaths to begin with, and I just=20
need a bit more time to wrap my head around it!)
Now here's the tricky example. With co_foo syntax:
task<string> read(string filename, string suffix)
{
istream fi =3D co_await open(filename);
string ret, chunk;
while((chunk =3D co_await fi.read()).size())
ret +=3D chunk + suffix;
return ret;
}
(I'm guessing that task<T> is just another way to spell nonstd::future<T>.)
In future-based syntax, this loop would be rather messy:
nonstd::future<string> read_impl(string ret, istream fi)
{
return fi.read().on_value_f(
[ret =3D std::move(ret), fi =3D std::move(fi)](string chunk) mutable
{
if (chunk.size()) {
ret +=3D chunk + suffix;
return read_impl(std::move(ret), fi);
} else {
return nonstd::make_ready_future<string>(std::move(ret));
}
}
);
}
nonstd::future<string> read(string filename, string suffix)
{
return open(filename).on_value_f([](istream fi) {
return read_impl("", std::move(fi));
});
}
(Notice that in both Herb's co_foo example and in mine, we ignore the fact=
=20
that the initialization of `istream fi` from the awaited value of=20
`open(...)` is highly likely to be slicing away important information.=20
Let's assume that this is some STL2-ish "value-semantic istream" that=20
doesn't care about slicing issues.)
Personally I'm also skeptical of the Coroutines TS package (weird keywords,=
=20
lots and lots of compiler magic, unclear customizability), but I do have to=
=20
say that the "future.then" approach is... *suboptimal*. We desperately need=
=20
*some* kind of idiom for working with continuations in C++, and Coroutines=
=20
TS is gamely attempting to tackle that problem head-on.
=E2=80=93Arthur
--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/e5d747e6-3a73-45d9-b71f-8ca77e629ae9%40isocpp.or=
g.
------=_Part_3576_1991041374.1520550253462
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, March 8, 2018 at 9:12:14 AM UTC-8, Nicol Bola=
s wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
[...]<br>The way the resumable expressions system handled this was to force=
you to do what the Coroutines TS effectively does when you invoke `co_awai=
t` and such: manually wrap your resumable function in a hidden lambda that =
stores a promise type and returns a future hooked into it.<br><br>The <i>en=
tire point</i> of the Coroutines TS is to keep you from having to write suc=
h boilerplate. Every design decision is based on that.<br>[...]</div><div>`=
co_await`-style coding handles this with no manual intervention. Herb Sutte=
r made a <a href=3D"https://channel9.msdn.com/events/Build/2013/2-306" targ=
et=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.=
google.com/url?q\x3dhttps%3A%2F%2Fchannel9.msdn.com%2Fevents%2FBuild%2F2013=
%2F2-306\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG_4CUrf4qpurGLd6RMoIWHCUGH=
mQ';return true;" onclick=3D"this.href=3D'https://www.google.com/ur=
l?q\x3dhttps%3A%2F%2Fchannel9.msdn.com%2Fevents%2FBuild%2F2013%2F2-306\x26s=
a\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG_4CUrf4qpurGLd6RMoIWHCUGHmQ';retur=
n true;">great presentation</a> a while back (skip ahead to around 51 minut=
es) on the failings of explicit callback-style continuations through lambda=
s and such, and demonstrated how use of `await` can make asynchronous code =
look exactly like synchronous code.<br><br>I'll reproduce his example h=
ere, in case you're unwilling to watch the video.<br><br>Here's the=
synchronous code. It reads from a given filename, appending `suffix` to ea=
ch "chunk" in the file. It's based on one of Microsoft's =
asynchronous file IO APIs (note that I've slightly adjusted some of the=
code):<br><br><div style=3D"background-color:rgb(250,250,250);border-color=
:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span sty=
le=3D"color:#008">string</span><span style=3D"color:#000"> read</span><span=
style=3D"color:#660">(</span><span style=3D"color:#008">string</span><span=
style=3D"color:#000"> filename</span><span style=3D"color:#660">,</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">string</span><s=
pan style=3D"color:#000"> suffix</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>=C2=A0 istream </span><span style=3D"color:#008=
">fi</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> open</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#000">filename</span><span style=3D"color:#66=
0">).</span><span style=3D"color:#008">get</span><span style=3D"color:#660"=
>();</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"colo=
r:#008">string</span><span style=3D"color:#000"> ret</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> chunk</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=
=3D"color:#008">while</span><span style=3D"color:#660">((</span><span style=
=3D"color:#000">chunk </span><span style=3D"color:#660">=3D</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#008">fi</span><span style=
=3D"color:#660">.</span><span style=3D"color:#000">read</span><span style=
=3D"color:#660">().</span><span style=3D"color:#008">get</span><span style=
=3D"color:#660">()).</span><span style=3D"color:#000">size</span><span styl=
e=3D"color:#660">())</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 ret=
</span><span style=3D"color:#660">+=3D</span><span style=3D"color:#000"> c=
hunk </span><span style=3D"color:#660">+</span><span style=3D"color:#000"> =
suffix</span><span style=3D"color:#660">;</span><span style=3D"color:#000">=
<br><br>=C2=A0 </span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> ret</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span></div></code>=
</div><br>All of the `.get()` calls are there to convert asynchronous tasks=
into synchronous operations. Our goal is to take this code and make it asy=
nchronous to the caller.<br><br>That `while` loop is the pernicious part. Y=
ou have to invoke `fi.read()`, but then you have to provide a continuation =
function to it. That continuation function must provoke additional `fi.read=
()` calls as needed. And each of those calls must pass a continuation funct=
ion. Namely <i>itself</i>. That pretty much requires heap allocation, lambd=
as, and heap allocation of lambdas. Nobody wants to write that code, and no=
body wants to debug it.<br><br>The Coroutines TS equivalent would look like=
this:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span styl=
e=3D"color:#000">task</span><span style=3D"color:#080"><string></span=
><span style=3D"color:#000"> read</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#008">string</span><span style=3D"color:#000"> filenam=
e</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">string</span><span style=3D"color:#000"> suff=
ix</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
=C2=A0 istream </span><span style=3D"color:#008">fi</span><span style=3D"co=
lor:#000"> </span><span style=3D"color:#660">=3D</span><span style=3D"color=
:#000"> co_await open</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">filename</span><span style=3D"color:#660">);</span><span st=
yle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">string</spa=
n><span style=3D"color:#000"> ret</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> chunk</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">whi=
le</span><span style=3D"color:#660">((</span><span style=3D"color:#000">chu=
nk </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> =
co_await </span><span style=3D"color:#008">fi</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#000">read</span><span style=3D"color:#660=
">()).</span><span style=3D"color:#000">size</span><span style=3D"color:#66=
0">())</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 ret </span><span =
style=3D"color:#660">+=3D</span><span style=3D"color:#000"> chunk </span><s=
pan style=3D"color:#660">+</span><span style=3D"color:#000"> suffix</span><=
span style=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=C2=A0=
</span><span style=3D"color:#008">return</span><span style=3D"color:#000">=
ret</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><b=
r></span><span style=3D"color:#660">}</span></div></code></div><br>You <i>c=
annot</i> get code that is simpler than that.</div></div></blockquote><div>=
<br></div><div>IMHO, this is a good example of a problem that is hard with =
futures and easier with co_foo syntax.</div>For the record, let me tackle y=
our original example,<div><br><div class=3D"prettyprint" style=3D"backgroun=
d-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wra=
p: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><=
span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">future</span><span style=3D"color=
: #080;" class=3D"styled-by-prettify"><int></span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> async_call</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(...)</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> val </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> co_await std</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">async</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">some_functio=
n</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">...);</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 co_return val =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">+</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></div></code></div><br>This one is easy to =
do with something like Boost.Future. With <a href=3D"https://github.com/Quu=
xplusone/toy-dns/blob/bus/src/include/nonstd-future.h#L6">my own toy future=
s library</a>, it looks like this:</div><div><br></div><div class=3D"pretty=
print" style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb=
(187, 187, 187); word-wrap: break-word;"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">nonstd</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">futur=
e</span><span style=3D"color: #080;" class=3D"styled-by-prettify"><int&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> async_c=
all</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(...)</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> nonstd</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">async</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">some_function</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">...)</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">on_value</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">([](</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> val</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> val </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-by=
-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">});</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div><=
div><br></div><div>I even find this future-based version easier to understa=
nd (at the moment): I find it easier to trace the exceptional control flow =
"past" the on_value call, and just say "aha, if the future w=
as not satisfied with a value, then we'll propagate the exception."=
; =C2=A0With the co_foo-based version, IIUC, you have to remember that ever=
y "co_await" includes an implicit "co_throw", so that t=
he operand of the "co_return" statement will not be evaluated if =
some_function throws. (But most likely this is exactly as obvious in hindsi=
ght as the idea of exceptional codepaths to begin with, and I just need a b=
it more time to wrap my head around it!)</div><div><br></div><div>Now here&=
#39;s the tricky example. With co_foo syntax:</div><div><br></div><div><div=
class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); borde=
r: 1px solid rgb(187, 187, 187); word-wrap: break-word;"><code class=3D"pre=
ttyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify">task</span><span style=3D"color: #080;" class=3D"st=
yled-by-prettify"><string></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> read</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">string</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> filename</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">string</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> suffix</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 istream </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">fi</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> co_await open</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">filename</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
ret</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> chunk</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">while</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">((</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">chunk </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> co_await </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">fi</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">read</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>()).</span><span style=3D"color: #000;" class=3D"styled-by-prettify">size<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">())</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
ret </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> chunk </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">+</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> suffix</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> ret</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">}</span></div></code></div><span style=3D"font-family: m=
onospace; color: rgb(102, 102, 0);"><br></span>(I'm guessing that task&=
lt;T> is just another way to spell nonstd::future<T>.)</div><div>I=
n future-based syntax, this loop would be rather messy:</div><div><br></div=
><div><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 2=
50); border: 1px solid rgb(187, 187, 187); word-wrap: break-word;"><code cl=
ass=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">nonstd</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">future</span><span style=3D"color: #080;" class=3D"sty=
led-by-prettify"><string></span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> read_impl</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">string</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> ret</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> istrea=
m </span><span style=3D"color: #008;" class=3D"styled-by-prettify">fi</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">fi</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">read</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>().</span><span style=3D"color: #000;" class=3D"styled-by-prettify">on_val=
ue_f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">[</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">ret </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">move</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">ret</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">),</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">fi</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">move</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">fi</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">)](</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
chunk</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">mutable</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">chunk</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">size</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">())</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 ret </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">+=3D</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> chunk </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">+</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> suffix</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> read_impl</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">move</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">ret</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">),</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">fi</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
else</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0=
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">re=
turn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> nonst=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">make_ready_future=
</span><span style=3D"color: #080;" class=3D"styled-by-prettify"><string=
></span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">move</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">ret</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">));</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br><br>nonstd</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">fu=
ture</span><span style=3D"color: #080;" class=3D"styled-by-prettify"><st=
ring></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> r=
ead</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">string</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> filename</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">string</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> suffix</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> open</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">filename=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">).</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">on_value_f</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">([](</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">istream </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">fi</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> read_impl</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #080;" class=3D"styled-by=
-prettify">""</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">move</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">fi</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">));</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">});</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></div></code></div><div><br></div></div><di=
v><br></div><div>(Notice that in both Herb's co_foo example and in mine=
, we ignore the fact that the initialization of `istream fi` from the await=
ed value of `open(...)` is highly likely to be slicing away important infor=
mation. =C2=A0Let's assume that this is some STL2-ish "value-seman=
tic istream" that doesn't care about slicing issues.)</div><div><b=
r></div><div>Personally I'm also skeptical of the Coroutines TS package=
(weird keywords, lots and lots of compiler magic, unclear customizability)=
, but I do have to say that the "future.then" approach is...=C2=
=A0<i>suboptimal</i>. We desperately need <i>some</i> kind of idiom for wor=
king with continuations in C++, and Coroutines TS is gamely attempting to t=
ackle that problem head-on.</div><div><br></div><div>=E2=80=93Arthur</div><=
/div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/e5d747e6-3a73-45d9-b71f-8ca77e629ae9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e5d747e6-3a73-45d9-b71f-8ca77e629ae9=
%40isocpp.org</a>.<br />
------=_Part_3576_1991041374.1520550253462--
------=_Part_3575_1685621849.1520550253461--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 8 Mar 2018 17:49:15 -0800 (PST)
Raw View
------=_Part_3953_1938088206.1520560155195
Content-Type: multipart/alternative;
boundary="----=_Part_3954_511289845.1520560155196"
------=_Part_3954_511289845.1520560155196
Content-Type: text/plain; charset="UTF-8"
On Thursday, March 8, 2018 at 6:04:13 PM UTC-5, Arthur O'Dwyer wrote:
>
> (Notice that in both Herb's co_foo example and in mine, we ignore the fact
> that the initialization of `istream fi` from the awaited value of
> `open(...)` is highly likely to be slicing away important information.
> Let's assume that this is some STL2-ish "value-semantic istream" that
> doesn't care about slicing issues.)
>
I don't think he was talking about std::istream. I'm guessing that's some
Microsoft-defined asynchronous stream type.
> Personally I'm also skeptical of the Coroutines TS package (weird
> keywords, lots and lots of compiler magic, unclear customizability), but I
> do have to say that the "future.then" approach is... *suboptimal*. We
> desperately need *some* kind of idiom for working with continuations in
> C++, and Coroutines TS is gamely attempting to tackle that problem head-on.
>
The only thing I disagree with here is that the "future.then" approach is
suboptimal. I think it's perfectly reasonable to tie "thing that generates
a value" with "apply process which manipulates a generated value, producing
a new value". Now granted, I wouldn't put that in `future<T>`; I think it
would make far more sense in a `task<T>` type, which represents a
potentially asynchronous execution. Having such a division would allow us
to avoid the terrible mistake of `std::async`'s return type, as well as
represent ways of providing executors and so forth.
The problem with `.then` and similar continuation interfaces is that it is
such a terrible interface *to use*. Despite how logical it is conceptually,
it leads to such difficult to manage code in non-trivial cases that we have
to introduce whole new language features just to be able to work with it in
a reasonable fashion.
I don't much care for the Coroutines TS. It doesn't really mirror the way I
normally work with tasks, and the lack of a form of "future.then" that
allows control over exactly where asychronous tasks get executed makes it a
non-starter to me. I personally would like to see resumable functions or
its equivalent get into the standard at some point, even if it is
*alongside* the Coroutines TS, just so that we can have generators that
don't suck.
But I simply cannot deny that the Coroutines TS, from a human readability
perspective, is absolutely *peerless* at its intended use case.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/344a4b64-f16b-4cc9-aa23-69f179e6ad0b%40isocpp.org.
------=_Part_3954_511289845.1520560155196
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, March 8, 2018 at 6:04:13 PM UTC-5, Arthur O&#=
39;Dwyer wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
">(Notice that in both Herb's co_foo example and in mine, we ignore the=
fact that the initialization of `istream fi` from the awaited value of `op=
en(...)` is highly likely to be slicing away important information. =C2=A0L=
et's assume that this is some STL2-ish "value-semantic istream&quo=
t; that doesn't care about slicing issues.)</div></blockquote><div><br>=
I don't think he was talking about std::istream. I'm guessing that&=
#39;s some Microsoft-defined asynchronous stream type.<br>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>Pe=
rsonally I'm also skeptical of the Coroutines TS package (weird keyword=
s, lots and lots of compiler magic, unclear customizability), but I do have=
to say that the "future.then" approach is...=C2=A0<i>suboptimal<=
/i>. We desperately need <i>some</i> kind of idiom for working with continu=
ations in C++, and Coroutines TS is gamely attempting to tackle that proble=
m head-on.</div></div></blockquote><div><br>The only thing I disagree with =
here is that the "future.then" approach is suboptimal. I think it=
's perfectly reasonable to tie "thing that generates a value"=
with "apply process which manipulates a generated value, producing a =
new value". Now granted, I wouldn't put that in `future<T>`;=
I think it would make far more sense in a `task<T>` type, which repr=
esents a potentially asynchronous execution. Having such a division would a=
llow us to avoid the terrible mistake of `std::async`'s return type, as=
well as represent ways of providing executors and so forth.<br><br>The pro=
blem with `.then` and similar continuation interfaces is that it is such a =
terrible interface <i>to use</i>. Despite how logical it is conceptually, i=
t leads to such difficult to manage code in non-trivial cases that we have =
to introduce whole new language features just to be able to work with it in=
a reasonable fashion.<br><br>I don't much care for the Coroutines TS. =
It doesn't really mirror the way I normally work with tasks, and the la=
ck of a form of "future.then" that allows control over exactly wh=
ere asychronous tasks get executed makes it a non-starter to me. I personal=
ly would like to see resumable functions or its equivalent get into the sta=
ndard at some point, even if it is <i>alongside</i> the Coroutines TS, just=
so that we can have generators that don't suck.<br><br>But I simply ca=
nnot deny that the Coroutines TS, from a human readability perspective, is =
absolutely <i>peerless</i> at its intended use case. <br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/344a4b64-f16b-4cc9-aa23-69f179e6ad0b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/344a4b64-f16b-4cc9-aa23-69f179e6ad0b=
%40isocpp.org</a>.<br />
------=_Part_3954_511289845.1520560155196--
------=_Part_3953_1938088206.1520560155195--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Fri, 9 Mar 2018 02:19:09 -0600
Raw View
--001a114af56854e53d0566f67271
Content-Type: text/plain; charset="UTF-8"
On Thu, Mar 8, 2018 at 7:43 AM, Todd Fleming <tbfleming@gmail.com> wrote:
> On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wrote:
>>
>> I think you (and others) misunderstood my idea -- I do not advocate
>> against current proposal, I am aiming only at one aspect of it -- namely
>> hiding coroutine behind "plain function" declaration. In my idea compiler
>> can generate precisely same language constructs during coroutine
>> "instantiation" (as it does in current proposal) -- same Awaitable<T> as
>> return types, etc.
>>
>
>
>
>> And yet it is one of selling points -- unfortunately it requires optional
>> compiler optimization, i.e. you can't rely on it. Also, it requires
>> compiler to be able to observe coroutine body, which naturally leads to a
>> question -- "why hiding it behind 'plain function' facade at all?". Why
>> don't we allow user to make related decisions explicitly (like where
>> coroutine frame will be allocated).
>>
>> Current proposal leads to a situation where I can't use coroutine in
>> *noexcept* function -- because I can't rely on compiler to use heap
>> allocation elision.
>>
>>
> Instead of using templates as an analogy, how about lambda functions?
>
> If lambda functions were like the current stackless coroutine proposal:
>
> - Type erasure would be mandatory, not opt-in.
> - Lambda functions would always live on the heap, except when the
> optimizer finds a way not to.
>
> If the proposal was more like lambda functions:
>
> - The user could opt into type erasure.
> - The coroutine object could live on the stack, or inside another
> object, or anywhere else.
>
>
Yep, that is a good analogy too. And my point was that it opens few doors
(if we need them), namely:
- ability to deal with stack machine object directly (i.e. allocate it on
the stack, call it's methods,etc), which makes heap elision optimization
irrelevant
- those methods can be inlined
- treat other coroutine calls made from this couroutine differently, i.e.:
we could flip this convention:
future<void> coro1()
{
auto x = co_await coro2(); // suspend here until coro2 is in "data
ready" state
auto y = coro2(); // no suspend
}
to this one (note that fundamentally we change nothing -- we still need a
way to distinguish between two types of calls):
coroutine void coro1()
{
auto x = coro2()(); // can suspend, if coro2 is awaitable
coro2 c2;
auto y = co_nowait c2(); // no suspend, I suspect this use case
will be rare
// or auto y = c2.resume(); // kick off coro2 until first suspend
return; // no need for co_return
}
- and few others I no longer remember :-)
Keep in mind I don't insist on these changes, but idea was presented to
with aim to make these options available in context of current Coroutine TS.
Other notes:
>
> - An unwrapped coroutine object probably wouldn't be callable. It may
> have an inconvenient interface that's only useful for wrappers to use.
> - The current proposal needs changes to std::future; this alternate
> idea may need additional changes. Maybe std::promise could do the type
> erasure for the async case?
> - My initial guess is the object couldn't be copyable or movable; it'd
> have to be RVO'ed to its final location.
>
> Todd
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/
> isocpp.org/d/topic/std-proposals/jJIO4ChPf-0/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/a3a1cd56-29ab-482b-
> accb-0a0208ef2154%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a3a1cd56-29ab-482b-accb-0a0208ef2154%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP5FN%2Byjc87VF%3D%2BdMbA69em5z-Qe7%2BNh6frfvZx0i%3D7T5g%40mail.gmail.com.
--001a114af56854e53d0566f67271
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Mar 8, 2018 at 7:43 AM, Todd Fleming <span dir=3D"ltr"><<a href=3D"m=
ailto:tbfleming@gmail.com" target=3D"_blank">tbfleming@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=
=3D"">On Wednesday, March 7, 2018 at 10:07:37 PM UTC-5, Michael Kilburn wro=
te:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D"g=
mail_quote"><div>I think you (and others) misunderstood my idea -- I do not=
advocate against current proposal, I am aiming only at one aspect of it --=
namely hiding coroutine behind "plain function" declaration. In =
my idea compiler can generate precisely same language constructs during cor=
outine "instantiation" (as it does in current proposal) -- same A=
waitable<T> as return types, etc.=C2=A0</div></div></div></blockquote=
><div><br></div><div>=C2=A0</div></span><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><div>And yet it is one of =
selling points -- unfortunately it requires optional compiler optimization,=
i.e. you can't rely on it. Also, it requires compiler to be able to ob=
serve coroutine body, which naturally leads to a question -- "why hidi=
ng it behind 'plain function' facade at all?". Why don't w=
e allow user to make related decisions explicitly (like where coroutine fra=
me will be allocated).</div><span class=3D""><div><br></div><div>Current pr=
oposal leads to a situation where I can't use coroutine in <i>noexcept<=
/i> function -- because I can't rely on compiler to use heap allocation=
elision.</div><div><br></div></span></div></div></blockquote><div>=C2=A0</=
div><div><div>Instead of using templates as an analogy, how about lambda fu=
nctions?</div><div><br></div><div>If lambda functions were like the current=
stackless coroutine proposal:</div><div><ul><li>Type erasure would be mand=
atory, not opt-in.<br></li><li>Lambda functions would always live on the he=
ap, except when the optimizer finds a way not to.</li></ul></div><div>If th=
e proposal was more like lambda functions:</div><div><ul><li>The user could=
opt into type erasure.<br></li><li>The coroutine object could live on the =
stack, or inside another object, or anywhere else.<br></li></ul></div></div=
></div></blockquote><div><br></div><div>Yep, that is a good analogy too. An=
d my point was that it opens few doors (if we need them), namely:</div><div=
>- ability to deal with stack machine object directly (i.e. allocate it on =
the stack, call it's methods,etc), which makes heap elision optimizatio=
n irrelevant</div><div>- those methods can be inlined</div><div>- treat oth=
er coroutine calls made from this couroutine differently, i.e.:</div><div><=
br></div><div>we could flip this convention:</div></div></div><blockquote s=
tyle=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extr=
a"><div class=3D"gmail_quote"><div><font face=3D"monospace, monospace"><br>=
</font></div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quo=
te"><div><font face=3D"monospace, monospace">future<void> coro1()</fo=
nt></div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<div><font face=3D"monospace, monospace">{=C2=A0</font></div></div></div><d=
iv class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"mono=
space, monospace">=C2=A0 =C2=A0 auto x =3D co_await coro2();=C2=A0 // suspe=
nd here until coro2 is in "data ready" state</font></div></div></=
div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=
=3D"monospace, monospace">=C2=A0 =C2=A0 auto y =3D coro2();=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0// no suspend</font></div></div></div><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"monospace, m=
onospace">}</font></div></div></div><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div><font face=3D"monospace, monospace"><br></font></div>=
</div></div></blockquote><font face=3D"arial, helvetica, sans-serif">to thi=
s one (note that fundamentally we change nothing -- we still need a way to =
distinguish between two types of calls):<br></font><blockquote style=3D"mar=
gin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div><font face=3D"monospace, monospace"><br></font></di=
v></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><d=
iv style=3D"color:rgb(34,34,34);font-size:small;font-style:normal;font-vari=
ant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacin=
g:normal;text-align:start;text-indent:0px;text-transform:none;white-space:n=
ormal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-st=
yle:initial;text-decoration-color:initial"><font face=3D"monospace, monospa=
ce">coroutine void coro1()</font></div></div></div></div><div class=3D"gmai=
l_extra"><div class=3D"gmail_quote"><div><div style=3D"color:rgb(34,34,34);=
font-size:small;font-style:normal;font-variant-ligatures:normal;font-varian=
t-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-i=
ndent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgroun=
d-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-colo=
r:initial"><font face=3D"monospace, monospace">{=C2=A0</font></div></div></=
div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><div s=
tyle=3D"color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-=
ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:no=
rmal;text-align:start;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:=
initial;text-decoration-color:initial"><font face=3D"monospace, monospace">=
=C2=A0 =C2=A0 auto x =3D coro2()();=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0// can suspend, if coro2 is awaitable</font></div></div><div styl=
e=3D"color:rgb(34,34,34);font-size:small;font-style:normal;font-variant-lig=
atures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:ini=
tial;text-decoration-color:initial"><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0=C2=A0<span style=3D"color:rgb(34,34,34);font-family:monospace,mo=
nospace;font-size:small;font-style:normal;font-variant-ligatures:normal;fon=
t-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:star=
t;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;b=
ackground-color:rgb(255,255,255);text-decoration-style:initial;text-decorat=
ion-color:initial;float:none;display:inline">coro2 c2;</span></font></div><=
/div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><div =
style=3D"color:rgb(34,34,34);font-size:small;font-style:normal;font-variant=
-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:n=
ormal;text-align:start;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style=
:initial;text-decoration-color:initial"><font face=3D"monospace, monospace"=
>=C2=A0 =C2=A0 auto y =3D=20
<span style=3D"color:rgb(34,34,34);font-size:small;font-style:normal;font-v=
ariant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spa=
cing:normal;text-align:start;text-indent:0px;text-transform:none;white-spac=
e:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration=
-style:initial;text-decoration-color:initial;float:none;display:inline">co_=
nowait</span>=C2=A0c2();=C2=A0 =C2=A0 =C2=A0 =C2=A0 // no suspend, I suspec=
t this use case will be rare</font></div></div></div></div></blockquote><bl=
ockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"=
gmail_extra"><div class=3D"gmail_quote"><div style=3D"color:rgb(34,34,34);f=
ont-size:small;font-style:normal;font-variant-ligatures:normal;font-variant=
-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-in=
dent:0px;text-transform:none;white-space:normal;word-spacing:0px;background=
-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color=
:initial"><font face=3D"monospace, monospace">=C2=A0 =C2=A0 // or=C2=A0
<span style=3D"color:rgb(34,34,34);font-family:monospace,monospace;font-siz=
e:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initia=
l;float:none;display:inline">auto y =3D<span>=C2=A0</span></span><span styl=
e=3D"color:rgb(34,34,34);font-family:monospace,monospace;font-size:small;fo=
nt-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font=
-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tra=
nsform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,25=
5,255);text-decoration-style:initial;text-decoration-color:initial;float:no=
ne;display:inline">c2.resume();=C2=A0 =C2=A0 // kick off coro2 until first =
suspend</span></font></div></div></div></blockquote><blockquote style=3D"ma=
rgin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><div><div style=3D"color:rgb(34,34,34);font-size:small;=
font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;fo=
nt-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-t=
ransform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,=
255,255);text-decoration-style:initial;text-decoration-color:initial"><font=
face=3D"monospace, monospace">=C2=A0 =C2=A0 return;=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// no =
need for co_return</font></div></div></div></div><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div><div style=3D"color:rgb(34,34,34);font-siz=
e:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initia=
l"><font face=3D"monospace, monospace">}</font></div></div></div></div></bl=
ockquote><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>
<div><br></div></div><div>- and few others I no longer remember :-)</div><d=
iv><br></div><div>Keep in mind I don't insist on these changes, but ide=
a was presented to with aim to make these options available in context of c=
urrent Coroutine TS.</div><div><br></div><div><br></div><div><br></div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left=
:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><div>Ot=
her notes:<br></div><div><ul><li>An unwrapped coroutine object probably wou=
ldn't be callable. It may have an inconvenient interface that's onl=
y useful for wrappers to use.<br></li><li>The current proposal needs change=
s to std::future; this alternate idea may need additional changes. Maybe st=
d::promise could do the type erasure for the async case?<br></li><li>My ini=
tial guess is the object couldn't be copyable or movable; it'd have=
to be RVO'ed to its final location.</li></ul></div></div><div>Todd</di=
v><div><br></div></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/jJIO4ChPf-0/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/<wbr>isocpp.org/d/topic/std-<wbr>proposals/j=
JIO4ChPf-0/<wbr>unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/a3a1cd56-29ab-482b-accb-0a0208ef2154%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/a3a1=
cd56-29ab-482b-<wbr>accb-0a0208ef2154%40isocpp.org</a><wbr>.<br>
</blockquote></div><br><br clear=3D"all"><div><br></div>-- <br><div class=
=3D"gmail_signature" data-smartmail=3D"gmail_signature">Sincerely yours,<br=
>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP5FN%2Byjc87VF%3D%2BdMbA69em5=
z-Qe7%2BNh6frfvZx0i%3D7T5g%40mail.gmail.com?utm_medium=3Demail&utm_source=
=3Dfooter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%=
2BnLVP5FN%2Byjc87VF%3D%2BdMbA69em5z-Qe7%2BNh6frfvZx0i%3D7T5g%40mail.gmail.c=
om</a>.<br />
--001a114af56854e53d0566f67271--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Fri, 9 Mar 2018 02:23:39 -0600
Raw View
--f403045fc1ae7112290566f682bd
Content-Type: text/plain; charset="UTF-8"
On Thu, Mar 8, 2018 at 8:08 AM, <inkwizytoryankes@gmail.com> wrote:
> On Thursday, March 8, 2018 at 10:54:24 AM UTC+1, Michael Kilburn wrote:
>>
>> On Thu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <crusad...@gmail.com>
>> wrote:
>>
>>> i.e. idea is not about coroutine implementation or semantic of generated
>>> functions -- it is about having every client to see entire coroutine. At
>>> this stage I really don't care exactly how resulting state machine will
>>> behave or what methods it will expose.
>>>
>>
>> One more argument -- consider template class and stackless coroutine.
>> Both of them are language provided mechanisms for transforming some code
>> into a C++ class -- i.e. fundamentally they do the same thing. In case of
>> template class there is no way to hide it's declaration from users -- at
>> any point entire class definition is visible to every user (even though you
>> may tuck away definition of individual member functions into some TU).
>> Stackless coroutine (in current form) hides resulting class -- this lack of
>> symmetry bothers me. It forces designers to come up with mechanisms
>> designed to workaround resulting problems (e.g. heap allocation elision
>> allows us to delegate allocation to a party that knows state machine frame
>> size and move allocation to stack, if certain criteria are met).
>>
>
> If I understand this problem correctly then we could alter current
> proposition to allow optional embedding coroutine state into return object
> instead of using allocation.
> We then would have 3 kinds: always heap, heap and fixed, only fixed.
> Return value will need have something like `std::aligned_storage` with
> some arbitrary size. Then if values of coroutine fit this storage then
> whole function compile and use this storage for variables, if not and we do
> not have enabled option for heap allocation then function fall to compile.
>
> This will have some drawback, one is you will need be careful when you
> stack generators you will need calculate size of things used inside (that
> are live during `co_yeld`):
> generator<int, 30 + sizeof(bar(0))> foo(int i)
> {
> int j = i;
> for (auto k : bar(i)) co_yeld (++j) * k;
> }
> Another is that return value will be not movable or copyable. Because
> otherwise you will need define how it will handle "local variables" when
> storage will be copied.
>
As I said before -- what you are going to do with newly available design
options is a different story. As far as I am concerned -- coroutine
translation step may generate exactly same code (with keywords and all)
that current TS suggests. I.e. the only effect would be that all coroutines
will become inline. Though, I certainly would like to be able to control
frame allocation.
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6vitfj%2BLTpbQZhRVw%2BsOVC988JX_qw6K%2B7zsrBq%2BgwsQ%40mail.gmail.com.
--f403045fc1ae7112290566f682bd
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Mar 8, 2018 at 8:08 AM, <span dir=3D"ltr"><<a href=3D"mailto:inkwiz=
ytoryankes@gmail.com" target=3D"_blank">inkwizytoryankes@gmail.com</a>><=
/span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Thursda=
y, March 8, 2018 at 10:54:24 AM UTC+1, Michael Kilburn wrote:<span class=3D=
""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote">On Thu, Mar 8, 2018 at 12:15 AM, Michael Kilburn <span dir=
=3D"ltr"><<a rel=3D"nofollow">crusad...@gmail.com</a>></span> wrote:<=
br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail=
_quote"><div>i.e. idea is not about coroutine implementation or semantic of=
generated functions -- it is about having every client to see entire corou=
tine. At this stage I really don't care exactly how resulting state mac=
hine will behave or what methods it will expose.<br></div></div></div></div=
></blockquote><div><br></div><div>One more argument -- consider template cl=
ass and stackless coroutine. Both of them are language provided mechanisms =
for transforming some code into a C++ class -- i.e. fundamentally they do t=
he same thing. In case of template class there is no way to hide it's d=
eclaration from users -- at any point entire class definition is visible to=
every user (even though you may tuck away definition of individual member =
functions into some TU). Stackless coroutine (in current form) hides result=
ing class -- this lack of symmetry bothers me. It forces designers to come =
up with mechanisms designed to workaround resulting problems (e.g. heap all=
ocation elision allows us to delegate allocation to a party that knows stat=
e machine frame size and move allocation to stack, if certain criteria are =
met).</div></div></div></div></blockquote></span><div>=C2=A0<br>If I unders=
tand this problem correctly then we could alter current=20
proposition to allow optional embedding coroutine state into return=20
object instead of using allocation.<br>We then would have 3 kinds: always h=
eap, heap and fixed, only fixed.<br>Return value will need have something l=
ike `std::aligned_storage` with some arbitrary size. Then if values of coro=
utine fit this storage then whole function compile and use this storage for=
variables, if not and we do not have enabled option for heap allocation th=
en function fall to compile.<br><br>This will have some drawback, one is yo=
u will need be careful when you stack generators you will need calculate si=
ze of things used inside (that are live during `co_yeld`):<br><div style=3D=
"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-sty=
le:solid;border-width:1px" class=3D"m_-8855168673231473177prettyprint"><cod=
e class=3D"m_-8855168673231473177prettyprint"><div class=3D"m_-885516867323=
1473177subprettyprint"><span style=3D"color:#000" class=3D"m_-8855168673231=
473177styled-by-prettify">generator</span><span style=3D"color:#660" class=
=3D"m_-8855168673231473177styled-by-prettify"><</span><span style=3D"col=
or:#008" class=3D"m_-8855168673231473177styled-by-prettify">int</span><span=
style=3D"color:#660" class=3D"m_-8855168673231473177styled-by-prettify">,<=
/span><span style=3D"color:#000" class=3D"m_-8855168673231473177styled-by-p=
rettify"> </span><span style=3D"color:#066" class=3D"m_-8855168673231473177=
styled-by-prettify">30</span><span style=3D"color:#000" class=3D"m_-8855168=
673231473177styled-by-prettify"> </span><span style=3D"color:#660" class=3D=
"m_-8855168673231473177styled-by-prettify">+</span><span style=3D"color:#00=
0" class=3D"m_-8855168673231473177styled-by-prettify"> </span><span style=
=3D"color:#008" class=3D"m_-8855168673231473177styled-by-prettify">sizeof</=
span><span style=3D"color:#660" class=3D"m_-8855168673231473177styled-by-pr=
ettify">(</span><span style=3D"color:#000" class=3D"m_-8855168673231473177s=
tyled-by-prettify">bar</span><span style=3D"color:#660" class=3D"m_-8855168=
673231473177styled-by-prettify">(</span><span style=3D"color:#066" class=3D=
"m_-8855168673231473177styled-by-prettify">0</span><span style=3D"color:#66=
0" class=3D"m_-8855168673231473177styled-by-prettify">))></span><span st=
yle=3D"color:#000" class=3D"m_-8855168673231473177styled-by-prettify"> foo<=
/span><span style=3D"color:#660" class=3D"m_-8855168673231473177styled-by-p=
rettify">(</span><span style=3D"color:#008" class=3D"m_-8855168673231473177=
styled-by-prettify">int</span><span style=3D"color:#000" class=3D"m_-885516=
8673231473177styled-by-prettify"> i</span><span style=3D"color:#660" class=
=3D"m_-8855168673231473177styled-by-prettify">)</span><span style=3D"color:=
#000" class=3D"m_-8855168673231473177styled-by-prettify"><br></span><span s=
tyle=3D"color:#660" class=3D"m_-8855168673231473177styled-by-prettify">{</s=
pan><span style=3D"color:#000" class=3D"m_-8855168673231473177styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" class=3D"m_-8855=
168673231473177styled-by-prettify">int</span><span style=3D"color:#000" cla=
ss=3D"m_-8855168673231473177styled-by-prettify"> j </span><span style=3D"co=
lor:#660" class=3D"m_-8855168673231473177styled-by-prettify">=3D</span><spa=
n style=3D"color:#000" class=3D"m_-8855168673231473177styled-by-prettify"> =
i</span><span style=3D"color:#660" class=3D"m_-8855168673231473177styled-by=
-prettify">;</span><span style=3D"color:#000" class=3D"m_-88551686732314731=
77styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" c=
lass=3D"m_-8855168673231473177styled-by-prettify">for</span><span style=3D"=
color:#000" class=3D"m_-8855168673231473177styled-by-prettify"> </span><spa=
n style=3D"color:#660" class=3D"m_-8855168673231473177styled-by-prettify">(=
</span><span style=3D"color:#008" class=3D"m_-8855168673231473177styled-by-=
prettify">auto</span><span style=3D"color:#000" class=3D"m_-885516867323147=
3177styled-by-prettify"> k </span><span style=3D"color:#660" class=3D"m_-88=
55168673231473177styled-by-prettify">:</span><span style=3D"color:#000" cla=
ss=3D"m_-8855168673231473177styled-by-prettify"> bar</span><span style=3D"c=
olor:#660" class=3D"m_-8855168673231473177styled-by-prettify">(</span><span=
style=3D"color:#000" class=3D"m_-8855168673231473177styled-by-prettify">i<=
/span><span style=3D"color:#660" class=3D"m_-8855168673231473177styled-by-p=
rettify">))</span><span style=3D"color:#000" class=3D"m_-885516867323147317=
7styled-by-prettify"> co_yeld </span><span style=3D"color:#660" class=3D"m_=
-8855168673231473177styled-by-prettify">(++</span><span style=3D"color:#000=
" class=3D"m_-8855168673231473177styled-by-prettify">j</span><span style=3D=
"color:#660" class=3D"m_-8855168673231473177styled-by-prettify">)</span><sp=
an style=3D"color:#000" class=3D"m_-8855168673231473177styled-by-prettify">=
</span><span style=3D"color:#660" class=3D"m_-8855168673231473177styled-by=
-prettify">*</span><span style=3D"color:#000" class=3D"m_-88551686732314731=
77styled-by-prettify"> k</span><span style=3D"color:#660" class=3D"m_-88551=
68673231473177styled-by-prettify">;</span><span style=3D"color:#000" class=
=3D"m_-8855168673231473177styled-by-prettify"><br></span><span style=3D"col=
or:#660" class=3D"m_-8855168673231473177styled-by-prettify">}</span><span s=
tyle=3D"color:#000" class=3D"m_-8855168673231473177styled-by-prettify"><br>=
</span></div></code></div>Another is that return value will be not movable =
or copyable. Because otherwise you will need define how it will handle &quo=
t;local variables" when storage will be copied.<br></div></div></block=
quote><div><br></div><div>As I said before -- what you are going to do with=
newly available design options is a different story. As far as I am concer=
ned -- coroutine translation step may generate exactly same code (with keyw=
ords and all) that current TS suggests. I.e. the only effect would be that =
all coroutines will become inline. Though, I certainly would like to be abl=
e to control frame allocation.</div><div><br></div></div><div><br></div>-- =
<br><div class=3D"gmail_signature" data-smartmail=3D"gmail_signature">Since=
rely yours,<br>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP6vitfj%2BLTpbQZhRVw%2BsOVC98=
8JX_qw6K%2B7zsrBq%2BgwsQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Df=
ooter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnL=
VP6vitfj%2BLTpbQZhRVw%2BsOVC988JX_qw6K%2B7zsrBq%2BgwsQ%40mail.gmail.com</a>=
..<br />
--f403045fc1ae7112290566f682bd--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Fri, 9 Mar 2018 02:35:14 -0600
Raw View
--f4f5e807fe84d9f5830566f6ab0f
Content-Type: text/plain; charset="UTF-8"
On Thu, Mar 8, 2018 at 10:55 AM, Lee Howes <xrikcus@gmail.com> wrote:
> > Ultimately, stackless coroutine is a C++ object with methods like
> resume()/etc. I don't see why you shouldn't be able to treat it as such --
> i.e. storing it as member variable of another class and access in a
> virtual function.
>
> Maybe I'm missing something here. You want the compiler to be able to see
> the body of the called coroutine, as I understand it.
>
yes, it will be able to see body, resulting state machine object, frame
size, etc
> To be clear I am saying I need to be able to do something like:
>
> class Foo {
> virtual Awaitable bar();
> };
>
> co_await my_foo->bar();
>
Hmm... I guess it should be possible:
coroutine void coro_bar(...) { ... }
class Foo {
virtual Awaitable bar() { return cb_(); }
coro_bar cb_; // an instance of state-machine class generated from
coro_bar's definition
};
does it make sense? I didn't think about it this way, but it should
probably work.
Now, you also said:
> > Nothing prevents you from hiding state machine object (generated from
> couroutine declaration) behind a function manually
>
> So I *think* you are saying that you can have a strictly visible coroutine
> that you can wrap in an async call to heap allocate it in case you want to
> pass the awaitable around, do some bulk collect operation or whatever. Is
> that right?
>
Yes, similar to code above. Not sure what do you mean by "bulk collection
operation", though.
> That's a reasonable point of view. At the moment we are pretty happy with
> the state of inlining when the functions are visible, and are more
> interested in ensuring there are no heap allocations in the example above,
> when they are not visible. We really can't afford to significantly increase
> the amount of compiler visible code we have, optimising for separate
> compilation is really the only option.
>
You mean compilation time will suffer because now every TU will be
translating that coroutine? It is the same problem as with templates. Plus,
if you really worry about these -- move coroutine declarions into separate
TU and hide them behind plain function.
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP5uATPfbgd1xgKyb%3Dc%2BTQKg1HJT%3Dmgd6K5YfmqybnFOFw%40mail.gmail.com.
--f4f5e807fe84d9f5830566f6ab0f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Mar 8, 2018 at 10:55 AM, Lee Howes <span dir=3D"ltr"><<a href=3D"mai=
lto:xrikcus@gmail.com" target=3D"_blank">xrikcus@gmail.com</a>></span> w=
rote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><=
span class=3D"m_-5546061419037698970gmail-im" style=3D"color:rgb(80,0,80);f=
ont-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant=
-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:n=
ormal;text-align:start;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style=
:initial;text-decoration-color:initial"><div><span style=3D"color:rgb(34,34=
,34);font-size:12.8px">> Ultimately, stackless coroutine is a C++ object=
with methods like resume()/etc. I don't see why you shouldn't be a=
ble to treat it as such -- i.e. storing it as member variable of another cl=
ass and access in a virtual=C2=A0 function.</span><br></div></span><div sty=
le=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;fon=
t-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-=
weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tran=
sform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255=
,255);text-decoration-style:initial;text-decoration-color:initial"><br></di=
v></span><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;fon=
t-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-=
caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-ind=
ent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-=
color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:=
initial">Maybe I'm missing something here. You want the compiler to be =
able to see the body of the called coroutine, as I understand it.</div></di=
v></blockquote><div><br></div><div>yes, it will be able to see body, result=
ing state machine object, frame size, etc</div><div><br></div><div>=C2=A0</=
div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div style=3D"color:rgb=
(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;=
font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;lett=
er-spacing:normal;text-align:start;text-indent:0px;text-transform:none;whit=
e-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-deco=
ration-style:initial;text-decoration-color:initial"> To be clear I am sayin=
g I need to be able to do something like:</div><div style=3D"color:rgb(34,3=
4,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-=
variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-sp=
acing:normal;text-align:start;text-indent:0px;text-transform:none;white-spa=
ce:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoratio=
n-style:initial;text-decoration-color:initial"><br></div><div style=3D"colo=
r:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:no=
rmal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400=
;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none=
;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text=
-decoration-style:initial;text-decoration-color:initial">class Foo {</div><=
div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.=
8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norma=
l;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;te=
xt-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(=
255,255,255);text-decoration-style:initial;text-decoration-color:initial">=
=C2=A0 virtual Awaitable bar();</div><div style=3D"color:rgb(34,34,34);font=
-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-li=
gatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:norm=
al;text-align:start;text-indent:0px;text-transform:none;white-space:normal;=
word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:in=
itial;text-decoration-color:initial">};</div><div style=3D"color:rgb(34,34,=
34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-va=
riant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spac=
ing:normal;text-align:start;text-indent:0px;text-transform:none;white-space=
:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-=
style:initial;text-decoration-color:initial"><br></div><div style=3D"color:=
rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:norm=
al;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;l=
etter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;w=
hite-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-d=
ecoration-style:initial;text-decoration-color:initial">co_await my_foo->=
bar();</div></div></blockquote><div><br></div><div>Hmm... I guess it should=
be possible:</div><div><br></div><div>coroutine void coro_bar(...) { ... }=
</div><div><br></div><div>
<div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-style:n=
ormal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:40=
0;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:non=
e;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-de=
coration-color:initial;font-size:12.8px;background-color:rgb(255,255,255)">=
class Foo {</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-s=
erif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norm=
al;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;text-decoration-styl=
e:initial;text-decoration-color:initial;font-size:12.8px;background-color:r=
gb(255,255,255)">=C2=A0 =C2=A0 virtual Awaitable bar() { return cb_(); }</d=
iv><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-styl=
e:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight=
:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:=
none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text=
-decoration-color:initial;font-size:12.8px;background-color:rgb(255,255,255=
)">=C2=A0 =C2=A0 coro_bar cb_;=C2=A0 // an instance of state-machine class =
generated from coro_bar's definition</div><div style=3D"color:rgb(34,34=
,34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;text-decoration-style:initial;text-decoration-color:initial;font-s=
ize:12.8px;background-color:rgb(255,255,255)">};</div><br></div><div>does i=
t make sense? I didn't think about it this way, but it should probably =
work.</div><div><br></div><div><br></div><blockquote class=3D"gmail_quote" =
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><span class=3D""><span class=3D"m_-5546061419037698970gmail-i=
m" style=3D"color:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8p=
x;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;=
font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text=
-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(25=
5,255,255);text-decoration-style:initial;text-decoration-color:initial"><di=
v><span style=3D"font-size:12.8px">Now, you also said:</span><br></div></sp=
an><div><span class=3D"m_-5546061419037698970gmail-im" style=3D"color:rgb(8=
0,0,80);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;fon=
t-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-=
spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-s=
pace:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decorat=
ion-style:initial;text-decoration-color:initial"><span style=3D"color:rgb(3=
4,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;fo=
nt-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decora=
tion-style:initial;text-decoration-color:initial;float:none;display:inline"=
>> Nothing prevents you from hiding state machine object (generated from=
couroutine declaration) behind a function manually</span><br></span></div>=
<div><br></div></span><div>So I *think* you are saying that you can have a =
strictly visible coroutine that you can wrap in an async call to heap alloc=
ate it in case you want to pass the awaitable around, do some bulk collect =
operation or whatever. Is that right?</div></div></blockquote><div><br></di=
v><div>Yes, similar to code above. Not sure what do you mean by "bulk =
collection operation", though.</div><div><br></div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>That's a reasonable =
point of view. At the moment we are pretty happy with the state of inlining=
when the functions are visible, and are more interested in ensuring there =
are no heap allocations in the example above, when they are not visible. We=
really can't afford to significantly increase the amount of compiler v=
isible code we have, optimising for separate compilation is really the only=
option.<br></div></div></blockquote><div><br></div><div>You mean compilati=
on time will suffer because now every TU will be translating that coroutine=
? It is the same problem as with templates. Plus, if you really worry about=
these -- move coroutine declarions into separate TU and hide them behind p=
lain function.</div><div><br></div></div>-- <br><div class=3D"gmail_signatu=
re" data-smartmail=3D"gmail_signature">Sincerely yours,<br>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP5uATPfbgd1xgKyb%3Dc%2BTQKg1H=
JT%3Dmgd6K5YfmqybnFOFw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP=
5uATPfbgd1xgKyb%3Dc%2BTQKg1HJT%3Dmgd6K5YfmqybnFOFw%40mail.gmail.com</a>.<br=
/>
--f4f5e807fe84d9f5830566f6ab0f--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Fri, 9 Mar 2018 03:10:33 -0600
Raw View
--001a114b0fce26b6a60566f72a1f
Content-Type: text/plain; charset="UTF-8"
On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> You are not being misunderstood. You're trying to equate all "stackless
> coroutine" proposals; you're claiming that they're all just minor
> variations of the same concept.
>
No, I don't. But you correctly noted that some of existing proposals
already have "always visible" feature. That is ok -- I presented this idea
in context of current proposal in order to enable options of:
- manually controlling generated state machine object (allocation, etc) to
make heap elision optimization irrelevant
- changing convention -- e.g. use co_nowait instead of c_await (see my
answer to Todd)
- few others
If you don't like any of these options -- naturally, that idea is a no go.
But maybe some of them can be appealing?
*They are not*. Coroutines TS is not just creating a resumable function;
> it's a lot more than that. It's implementing a specific model of
> coroutines, which is different from the model you're defining.
>
> If you want "just resumable functions", then you need to understand that
> this really is a completely different proposal with a completely different
> design from the Coroutines TS. It's not a slight modification of Coroutines
> TS (which is evidence in the fact that your design literally removes all of
> the Coroutines TS's keywords).
>
keywords maybe removed but their intended effect stays unchanged.
> Your design is a suspend-down coroutine model. When your kind of coroutine
> yields, it always returns to its nearest non-coroutine caller, who is
> responsible for scheduling its resumption at some point. Coroutines TS is a
> suspend-up coroutine model: the code responsible for scheduling its
> resumption is the code *inside* the coroutine, not necessarily its
> caller. If the code inside the coroutine suspends to the caller, that's
> because the particular coroutine chooses to.
>
> Generators are the classic case of suspend-down. That's why your design
> works especially well with them, and why the Coroutines TS works so poorly
> with them. Continuations however are a classic case of suspend-up. This is
> why your design requires lots of extra work to use them, while the
> Coroutines TS makes it look like synchronous code.
>
> Coroutines TS will never be as good at generators as your idea is. But
> neither will your idea be as good at asynchronous code transformations as
> the Coroutines TS is.
>
Again, the idea presented doesn't fundamentally change anything in current
proposal with respect to returned types (future/etc) or the way it
suspends. All it does is exposes generated state machine class to every
user, thus enabling certain options that designers may or may not take.
Compiler can see that current coroutine calls another coroutine and
>> generate required fluff automatically. You can introduce a new keyword (or
>> convention) that will allow you to call coroutine in other way (but I doubt
>> this need will be great).
>>
> - inlining of some of generated C++ object methods
>>
>
> Inlining is only relevant when dealing with suspend-down style coroutines.
> That is, generators and the like. Inlining is not relevant (or possible)
> when dealing with suspend-up continuations. This is why such inlining is an
> optimization to Coroutines TS rather than a requirement. It's a suspend-up
> model, so it does things in a suspend-up way.
>
True, I was thinking about other methods given coroutine object may have.
Maybe this would allow to avoid type erasure? I didn't think about it, tbh.
I see... one of the aims is to integrate coroutines with future/async
>> stuff... I am probably behind on all this. All async libs I looked at used
>> same approach -- public API consists of a function (async_foo) that takes a
>> callback. Then someone somewhere cranks the event loop which eventually
>> calls "process_events()" library function that in turn calls aforementioned
>> callback.
>>
>> So, for this library to add coroutine support you'd have to create second
>> inline function (or macro) coro_foo() that takes address of resume() method
>> of current coroutine, registers it using async_foo() and suspends current
>> coroutine. I.e. in this design you still have to add second version of your
>> async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fault is this
>> approach -- everything is clear and clean.
>>
>> Now, if library instead exports "future<int> foo()" -- there is no need
>> for coro_foo(), but implementation becomes less efficient and more complex.
>> Because of type erasures, having to allocate memory, having to move values
>> and other stuff (like synchronization). Am I right? Is it a good price for
>> not having to add a (rather simple) coro_foo()?
>>
>
> It all depends: is the person calling the async routine the one who
> actually has the continuation? The `future.then`-style interface allows
> anyone at any time to hook a continuation into the process. Your `coro_foo`
> style requires that the exact caller be the one who provides the
> continuation.
>
> And what if the continuation function itself needs a continuation? The
> caller has to provide that too. And what if the inner continuation needs to
> access something from the outer continuation? Well, you have to allocate
> that explicitly. And so forth.
>
How often it will happen? Your typical caller of a coroutine is probably
another coroutine that awaits on it. In this case it works just fine. In
others -- related boilerplate can be buried into some utility function(s).
> `co_await`-style coding handles this with no manual intervention. Herb
> Sutter made a great presentation
> <https://channel9.msdn.com/events/Build/2013/2-306> a while back (skip
> ahead to around 51 minutes) on the failings of explicit callback-style
> continuations through lambdas and such, and demonstrated how use of `await`
> can make asynchronous code look exactly like synchronous code.
>
> I'll reproduce his example here, in case you're unwilling to watch the
> video.
>
Ok, now that was below the belt. I did watch it.
Here's the synchronous code. It reads from a given filename, appending
> `suffix` to each "chunk" in the file. It's based on one of Microsoft's
> asynchronous file IO APIs (note that I've slightly adjusted some of the
> code):
>
<lots of snipping>
And your `coro_func` version would not work, due to the need of this code
> to continue itself. You'd have to write a lambda, heap-allocate it, and do
> a bunch of other stuff to make the explicit continuation code work.
>
Why it wouldn't work? coro_foo() will end up calling async_foo() passing my
current coroutine resume() as a callback and suspending (i.e. returning).
Code will be practically the same. I either fantastically missing something
or we are not on the same page.
The kind of design you've presented is exactly what the resumable
>>> expressions proposal used
>>> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>. Only
>>> it was a bit cleverer about it, such that you would just have a resumable
>>> function called "await" that could be overloaded for some "awaitable" type,
>>> which would do the scheduling and unpacking, returning the unpacked value
>>> once resumed.
>>>
>>
>>> You really should look at that proposal; it's clearly what you want. And
>>> yes, it was looked at, but it didn't move forward past P0114R0.
>>>
>>
>> Thank you, I will read it. But as I said -- it isn't what I was talking
>> about.
>>
>
> How can you say it isn't what you were talking about when you *haven't
> read it*?
>
I meant I did not propose a new design -- I presented an idea (for current
design) that may change it a bit opening up some options.
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1b-uACR2ygB0z1hDA3w%40mail.gmail.com.
--001a114b0fce26b6a60566f72a1f
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On T=
hu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>You are=
not being misunderstood. You're trying to equate all "stackless=
=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br></div></div></blockquote><div><br></=
div><div>No, I don't. But you correctly noted that some of existing pro=
posals already have "always visible" feature. That is ok -- I pre=
sented this idea in context of current proposal in order to enable options =
of:</div><div>- manually controlling generated state machine object (alloca=
tion, etc) to make heap elision optimization irrelevant</div><div>- changin=
g convention -- e.g. use co_nowait instead of c_await (see my answer to Tod=
d)</div><div>- few others</div><div><br></div><div>If you don't like an=
y of these options -- naturally, that idea is a no go. But maybe some of th=
em can be appealing?</div><div><br></div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div><i>They are not</i>. Coroutines TS is n=
ot just creating a resumable function; it's a lot more than that. It=
9;s implementing a specific model of coroutines, which is different from th=
e model you're defining.<br><br>If you want "just resumable functi=
ons", then you need to understand that this really is a completely dif=
ferent proposal with a completely different design from the Coroutines TS. =
It's not a slight modification of Coroutines TS (which is evidence in t=
he fact that your design literally removes all of the Coroutines TS's k=
eywords).<br></div></div></blockquote><div><br></div><div>keywords maybe re=
moved but their intended effect stays unchanged.</div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Your desig=
n is a=20
suspend-down coroutine model. When your kind of coroutine yields, it always=
returns
to its nearest non-coroutine caller, who is responsible for scheduling its=
=20
resumption at some point. Coroutines TS is a suspend-up coroutine model:
the code responsible for scheduling its resumption is the code <i>inside</=
i> the coroutine, not necessarily its caller. If the code inside the corout=
ine suspends to the caller, that's because the particular coroutine cho=
oses to.<br><br>Generators
are the classic case of suspend-down. That's why your design works=20
especially well with them, and why the Coroutines TS works so poorly with=
=20
them. Continuations however are a classic case of suspend-up. This is=20
why your design requires lots of extra work to use them, while the=20
Coroutines TS makes it look like synchronous code.<br><br>Coroutines TS wil=
l never be as good at generators as your idea is. But neither will your ide=
a be as good at asynchronous code transformations as the Coroutines TS is.<=
br></div></div></blockquote><div><br></div><div>Again, the idea presented d=
oesn't fundamentally change anything in current proposal with respect t=
o returned types (future/etc) or the way it suspends. All it does is expose=
s generated state machine class to every user, thus enabling certain option=
s that designers may or may not take.</div><div><br></div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div>Compiler can see that current coroutine calls another coroutine and =
generate required fluff automatically. You can introduce a new keyword (or =
convention) that will allow you to call coroutine in other way (but I doubt=
this need will be great).<br></div></div></div></div></blockquote></span><=
span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-=
left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><d=
iv class=3D"gmail_quote"><div>- inlining of some of generated C++ object me=
thods</div></div></div></blockquote></span><div><br>Inlining is only releva=
nt when dealing with suspend-down style coroutines. That is, generators and=
the like. Inlining is not relevant (or possible) when dealing with suspend=
-up continuations. This is why such inlining is an optimization to Coroutin=
es TS rather than a requirement. It's a suspend-up model, so it does th=
ings in a suspend-up way.<br></div></div></blockquote><div><br></div><div>T=
rue, I was thinking about other methods given coroutine object may have. Ma=
ybe this would allow to avoid type erasure? I didn't think about it, tb=
h.</div><div>=C2=A0</div><div><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div =
class=3D"gmail_quote"><span class=3D""><div>I see... one of the aims is to =
integrate coroutines with future/async stuff... I am probably behind on all=
this. All async libs I looked at used same approach -- public API consists=
of a function (async_foo) that takes a callback. Then someone somewhere cr=
anks the event loop which eventually calls "process_events()" lib=
rary function that in turn calls aforementioned callback.<br></div></span><=
span class=3D""><div><br></div><div>So, for this library to add coroutine s=
upport you'd have to create second inline function (or macro) coro_foo(=
) that takes address of resume() method of current coroutine, registers it =
using async_foo() and suspends current coroutine. I.e. in this design you s=
till have to add second version of your async_foo() -- a coroutine-aware wr=
apper coro_foo(). I see no fault is this approach -- everything is clear an=
d clean.</div><div><br></div><div>Now, if library instead exports "fut=
ure<int> foo()" -- there is no need for coro_foo(), but implemen=
tation becomes less efficient and more complex. Because of type erasures, h=
aving to allocate memory, having to move values and other stuff (like synch=
ronization). Am I right? Is it a good price for not having to add a (rather=
simple) coro_foo()?<br></div></span></div></div></blockquote><div><br>It a=
ll depends: is the person calling the async routine the one who actually ha=
s the continuation? The `future.then`-style interface allows anyone at any =
time to hook a continuation into the process. Your `coro_foo` style require=
s that the exact caller be the one who provides the continuation.<br><br>An=
d what if the continuation function itself needs a continuation? The caller=
has to provide that too. And what if the inner continuation needs to acces=
s something from the outer continuation? Well, you have to allocate that ex=
plicitly. And so forth.<br></div></div></blockquote><div><br></div><div>How=
often it will happen? Your typical caller of a coroutine is probably anoth=
er coroutine that awaits on it. In this case it works just fine. In others =
-- related boilerplate can be buried into some utility function(s).</div><d=
iv><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div>`co_await`-style coding handles this with no manual intervention. H=
erb Sutter made a <a href=3D"https://channel9.msdn.com/events/Build/2013/2-=
306" target=3D"_blank">great presentation</a> a while back (skip ahead to a=
round 51 minutes) on the failings of explicit callback-style continuations =
through lambdas and such, and demonstrated how use of `await` can make asyn=
chronous code look exactly like synchronous code.<br><br>I'll reproduce=
his example here, in case you're unwilling to watch the video.<br></di=
v></div></blockquote><div><br></div><div>Ok, now that was below the belt. I=
did watch it.</div><div><br></div><div><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div>Here's the synchronous code. It reads from =
a given filename, appending `suffix` to each "chunk" in the file.=
It's based on one of Microsoft's asynchronous file IO APIs (note t=
hat I've slightly adjusted some of the code):<br></div></div></blockquo=
te><div>=C2=A0</div><div><lots of snipping>=C2=A0<br></div><div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>And your `coro_fu=
nc` version would not work, due to the need of this code to continue itself=
.. You'd have to write a lambda, heap-allocate it, and do a bunch of oth=
er stuff to make the explicit continuation code work.<br></div></div></bloc=
kquote><div><br></div><div>Why it wouldn't work? coro_foo() will end up=
calling async_foo() passing my current coroutine resume() as a callback an=
d suspending (i.e. returning). Code will be practically the same. I either =
fantastically missing something or we are not on the same page.</div><div><=
br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><sp=
an class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div=
><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div>The kind of design you've presented is <a href=3D"http://open-std=
..org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf" rel=3D"nofollow" target=
=3D"_blank">exactly what the resumable expressions proposal used</a>. Only =
it was a bit cleverer about it, such that you would just have a resumable f=
unction called "await" that could be overloaded for some "aw=
aitable" type, which would do the scheduling and unpacking, returning =
the unpacked value once resumed.=C2=A0</div></div></blockquote><blockquote =
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid=
;padding-left:1ex"><div dir=3D"ltr"><div><br>You really should look at that=
proposal; it's clearly what you want. And yes, it was looked at, but i=
t didn't move forward past P0114R0.</div></div></blockquote><div><br></=
div><div>Thank you, I will read it. But as I said -- it isn't what I wa=
s talking about.</div></div></div></div></blockquote></span><div><br>How ca=
n you say it isn't what you were talking about when you <i>haven't =
read it</i>?</div></div></blockquote><div><br></div><div>I meant I did not =
propose a new design -- I presented an idea (for current design) that may c=
hange it a bit opening up some options.</div><div><br></div></div>-- <br><d=
iv class=3D"gmail_signature" data-smartmail=3D"gmail_signature">Sincerely y=
ours,<br>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1=
b-uACR2ygB0z1hDA3w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQ=
eo%3DJsjMJybNfa9O3MxSQu1b-uACR2ygB0z1hDA3w%40mail.gmail.com</a>.<br />
--001a114b0fce26b6a60566f72a1f--
.
Author: Lee Howes <xrikcus@gmail.com>
Date: Fri, 9 Mar 2018 09:30:28 -0800
Raw View
--0000000000000283de0566fe268b
Content-Type: text/plain; charset="UTF-8"
> coroutine void coro_bar(...) { ... }
> class Foo {
> virtual Awaitable bar() { return cb_(); }
> coro_bar cb_; // an instance of state-machine class generated from
coro_bar's definition
> };
> does it make sense? I didn't think about it this way, but it should
probably work.
You've added shared state. Now what happens if I want to do something like
this:
Foo f;
thread t([&](){await f.bar());
thread t2([&](){await f.bar());
t.join();
t2.join();
I need two copies of cb_, or for cb_ to use heap allocation magic to hide
that, or at the very least to synchronize the coroutine state.
> It is the same problem as with templates.
It certainly is. It is a huge problem.
move coroutine declarions into separate TU and hide them behind plain
function.
On 9 March 2018 at 01:10, Michael Kilburn <crusader.mike@gmail.com> wrote:
> On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>> You are not being misunderstood. You're trying to equate all "stackless
>> coroutine" proposals; you're claiming that they're all just minor
>> variations of the same concept.
>>
>
> No, I don't. But you correctly noted that some of existing proposals
> already have "always visible" feature. That is ok -- I presented this idea
> in context of current proposal in order to enable options of:
> - manually controlling generated state machine object (allocation, etc) to
> make heap elision optimization irrelevant
> - changing convention -- e.g. use co_nowait instead of c_await (see my
> answer to Todd)
> - few others
>
> If you don't like any of these options -- naturally, that idea is a no go.
> But maybe some of them can be appealing?
>
>
> *They are not*. Coroutines TS is not just creating a resumable function;
>> it's a lot more than that. It's implementing a specific model of
>> coroutines, which is different from the model you're defining.
>>
>> If you want "just resumable functions", then you need to understand that
>> this really is a completely different proposal with a completely different
>> design from the Coroutines TS. It's not a slight modification of Coroutines
>> TS (which is evidence in the fact that your design literally removes all of
>> the Coroutines TS's keywords).
>>
>
> keywords maybe removed but their intended effect stays unchanged.
>
>
>
>> Your design is a suspend-down coroutine model. When your kind of
>> coroutine yields, it always returns to its nearest non-coroutine caller,
>> who is responsible for scheduling its resumption at some point. Coroutines
>> TS is a suspend-up coroutine model: the code responsible for scheduling its
>> resumption is the code *inside* the coroutine, not necessarily its
>> caller. If the code inside the coroutine suspends to the caller, that's
>> because the particular coroutine chooses to.
>>
>> Generators are the classic case of suspend-down. That's why your design
>> works especially well with them, and why the Coroutines TS works so poorly
>> with them. Continuations however are a classic case of suspend-up. This is
>> why your design requires lots of extra work to use them, while the
>> Coroutines TS makes it look like synchronous code.
>>
>> Coroutines TS will never be as good at generators as your idea is. But
>> neither will your idea be as good at asynchronous code transformations as
>> the Coroutines TS is.
>>
>
> Again, the idea presented doesn't fundamentally change anything in current
> proposal with respect to returned types (future/etc) or the way it
> suspends. All it does is exposes generated state machine class to every
> user, thus enabling certain options that designers may or may not take.
>
>
> Compiler can see that current coroutine calls another coroutine and
>>> generate required fluff automatically. You can introduce a new keyword (or
>>> convention) that will allow you to call coroutine in other way (but I doubt
>>> this need will be great).
>>>
>> - inlining of some of generated C++ object methods
>>>
>>
>> Inlining is only relevant when dealing with suspend-down style
>> coroutines. That is, generators and the like. Inlining is not relevant (or
>> possible) when dealing with suspend-up continuations. This is why such
>> inlining is an optimization to Coroutines TS rather than a requirement.
>> It's a suspend-up model, so it does things in a suspend-up way.
>>
>
> True, I was thinking about other methods given coroutine object may have.
> Maybe this would allow to avoid type erasure? I didn't think about it, tbh.
>
>
> I see... one of the aims is to integrate coroutines with future/async
>>> stuff... I am probably behind on all this. All async libs I looked at used
>>> same approach -- public API consists of a function (async_foo) that takes a
>>> callback. Then someone somewhere cranks the event loop which eventually
>>> calls "process_events()" library function that in turn calls aforementioned
>>> callback.
>>>
>>> So, for this library to add coroutine support you'd have to create
>>> second inline function (or macro) coro_foo() that takes address of resume()
>>> method of current coroutine, registers it using async_foo() and suspends
>>> current coroutine. I.e. in this design you still have to add second version
>>> of your async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fault
>>> is this approach -- everything is clear and clean.
>>>
>>> Now, if library instead exports "future<int> foo()" -- there is no need
>>> for coro_foo(), but implementation becomes less efficient and more complex.
>>> Because of type erasures, having to allocate memory, having to move values
>>> and other stuff (like synchronization). Am I right? Is it a good price for
>>> not having to add a (rather simple) coro_foo()?
>>>
>>
>> It all depends: is the person calling the async routine the one who
>> actually has the continuation? The `future.then`-style interface allows
>> anyone at any time to hook a continuation into the process. Your `coro_foo`
>> style requires that the exact caller be the one who provides the
>> continuation.
>>
>> And what if the continuation function itself needs a continuation? The
>> caller has to provide that too. And what if the inner continuation needs to
>> access something from the outer continuation? Well, you have to allocate
>> that explicitly. And so forth.
>>
>
> How often it will happen? Your typical caller of a coroutine is probably
> another coroutine that awaits on it. In this case it works just fine. In
> others -- related boilerplate can be buried into some utility function(s).
>
>
>
>> `co_await`-style coding handles this with no manual intervention. Herb
>> Sutter made a great presentation
>> <https://channel9.msdn.com/events/Build/2013/2-306> a while back (skip
>> ahead to around 51 minutes) on the failings of explicit callback-style
>> continuations through lambdas and such, and demonstrated how use of `await`
>> can make asynchronous code look exactly like synchronous code.
>>
>> I'll reproduce his example here, in case you're unwilling to watch the
>> video.
>>
>
> Ok, now that was below the belt. I did watch it.
>
>
> Here's the synchronous code. It reads from a given filename, appending
>> `suffix` to each "chunk" in the file. It's based on one of Microsoft's
>> asynchronous file IO APIs (note that I've slightly adjusted some of the
>> code):
>>
>
> <lots of snipping>
>
> And your `coro_func` version would not work, due to the need of this code
>> to continue itself. You'd have to write a lambda, heap-allocate it, and do
>> a bunch of other stuff to make the explicit continuation code work.
>>
>
> Why it wouldn't work? coro_foo() will end up calling async_foo() passing
> my current coroutine resume() as a callback and suspending (i.e.
> returning). Code will be practically the same. I either fantastically
> missing something or we are not on the same page.
>
>
> The kind of design you've presented is exactly what the resumable
>>>> expressions proposal used
>>>> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>.
>>>> Only it was a bit cleverer about it, such that you would just have a
>>>> resumable function called "await" that could be overloaded for some
>>>> "awaitable" type, which would do the scheduling and unpacking, returning
>>>> the unpacked value once resumed.
>>>>
>>>
>>>> You really should look at that proposal; it's clearly what you want.
>>>> And yes, it was looked at, but it didn't move forward past P0114R0.
>>>>
>>>
>>> Thank you, I will read it. But as I said -- it isn't what I was talking
>>> about.
>>>
>>
>> How can you say it isn't what you were talking about when you *haven't
>> read it*?
>>
>
> I meant I did not propose a new design -- I presented an idea (for current
> design) that may change it a bit opening up some options.
>
> --
> Sincerely yours,
> Michael.
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1b-
> uACR2ygB0z1hDA3w%40mail.gmail.com
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1b-uACR2ygB0z1hDA3w%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNXr9GDvH92ZztR5iH7Xc8dy-%2BFL-_QFjFK3S1FQ%2BybJBg%40mail.gmail.com.
--0000000000000283de0566fe268b
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div style=3D"color:rgb(34,34,34);font-family:arial,sans-s=
erif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-=
variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;=
text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;bac=
kground-color:rgb(255,255,255);text-decoration-style:initial;text-decoratio=
n-color:initial">> coroutine void coro_bar(...) { ... }</div><div style=
=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-=
style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-we=
ight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transf=
orm:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,2=
55);text-decoration-style:initial;text-decoration-color:initial"><span styl=
e=3D"font-size:12.8px">> class Foo {</span><br></div><div style=3D"color=
:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:nor=
mal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;=
letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;=
white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-=
decoration-style:initial;text-decoration-color:initial"><div style=3D"color=
:rgb(34,34,34);font-family:arial,sans-serif;font-style:normal;font-variant-=
ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:no=
rmal;text-align:start;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px;text-decoration-style:initial;text-decoration-color:init=
ial;font-size:12.8px;background-color:rgb(255,255,255)">>=C2=A0 =C2=A0vi=
rtual Awaitable bar() { return cb_(); }</div><div style=3D"color:rgb(34,34,=
34);font-family:arial,sans-serif;font-style:normal;font-variant-ligatures:n=
ormal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-a=
lign:start;text-indent:0px;text-transform:none;white-space:normal;word-spac=
ing:0px;text-decoration-style:initial;text-decoration-color:initial;font-si=
ze:12.8px;background-color:rgb(255,255,255)">>=C2=A0 =C2=A0 =C2=A0coro_b=
ar cb_;=C2=A0 // an instance of state-machine class generated from coro_bar=
's definition</div><div style=3D"color:rgb(34,34,34);font-family:arial,=
sans-serif;font-style:normal;font-variant-ligatures:normal;font-variant-cap=
s:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent=
:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoratio=
n-style:initial;text-decoration-color:initial;font-size:12.8px;background-c=
olor:rgb(255,255,255)">> };</div><br></div><div style=3D"color:rgb(34,34=
,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-v=
ariant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spa=
cing:normal;text-align:start;text-indent:0px;text-transform:none;white-spac=
e:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration=
-style:initial;text-decoration-color:initial">> does it make sense? I di=
dn't think about it this way, but it should probably work.</div><span c=
lass=3D"gmail-im" style=3D"color:rgb(80,0,80);font-family:arial,sans-serif;=
font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-varia=
nt-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgrou=
nd-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-col=
or:initial"><div><span class=3D"gmail-im" style=3D"color:rgb(80,0,80);font-=
family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-lig=
atures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:ini=
tial;text-decoration-color:initial"><br></span></div>You've added share=
d state. Now what happens if I want to do something like this:</span><div><=
br></div><div>Foo f;</div><div>thread t([&](){await=C2=A0 f.bar());</di=
v><div><span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font=
-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-ca=
ps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-inden=
t:0px;text-transform:none;white-space:normal;word-spacing:0px;background-co=
lor:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:in=
itial;float:none;display:inline">thread t2([&](){await=C2=A0 f.bar());<=
/span><br></div><div>t.join();</div><div>t2.join();</div><div><br></div><di=
v>I need two copies of cb_, or for cb_ to use heap allocation magic to hide=
that, or at the very least to synchronize the coroutine state.</div><div><=
br></div><div>>=C2=A0<span style=3D"color:rgb(34,34,34);font-family:aria=
l,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:norm=
al;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-alig=
n:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-d=
ecoration-color:initial;float:none;display:inline"><span>=C2=A0</span>It is=
the same problem as with templates.=C2=A0</span></div><div><span style=3D"=
font-size:12.8px"><br></span></div><div><span style=3D"font-size:12.8px">It=
certainly is. It is a huge problem.</span></div><div><span style=3D"font-s=
ize:12.8px">move coroutine declarions into separate TU and hide them behind=
plain function.</span><br><br class=3D"gmail-Apple-interchange-newline"></=
div><div><br></div><div><br></div></div><div class=3D"gmail_extra"><br><div=
class=3D"gmail_quote">On 9 March 2018 at 01:10, Michael Kilburn <span dir=
=3D"ltr"><<a href=3D"mailto:crusader.mike@gmail.com" target=3D"_blank">c=
rusader.mike@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_=
quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<span class=3D"">On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <span dir=3D"=
ltr"><<a href=3D"mailto:jmckesson@gmail.com" target=3D"_blank">jmckesson=
@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>You are not being misunderstood. You're trying to equate =
all "stackless=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br></div></div></blockquote><div><br></=
div></span><div>No, I don't. But you correctly noted that some of exist=
ing proposals already have "always visible" feature. That is ok -=
- I presented this idea in context of current proposal in order to enable o=
ptions of:</div><div>- manually controlling generated state machine object =
(allocation, etc) to make heap elision optimization irrelevant</div><div>- =
changing convention -- e.g. use co_nowait instead of c_await (see my answer=
to Todd)</div><div>- few others</div><div><br></div><div>If you don't =
like any of these options -- naturally, that idea is a no go. But maybe som=
e of them can be appealing?</div><span class=3D""><div><br></div><div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><i>They are not</=
i>. Coroutines TS is not just creating a resumable function; it's a lot=
more than that. It's implementing a specific model of coroutines, whic=
h is different from the model you're defining.<br><br>If you want "=
;just resumable functions", then you need to understand that this real=
ly is a completely different proposal with a completely different design fr=
om the Coroutines TS. It's not a slight modification of Coroutines TS (=
which is evidence in the fact that your design literally removes all of the=
Coroutines TS's keywords).<br></div></div></blockquote><div><br></div>=
</span><div>keywords maybe removed but their intended effect stays unchange=
d.</div><span class=3D""><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div>Your design is a=20
suspend-down coroutine model. When your kind of coroutine yields, it always=
returns
to its nearest non-coroutine caller, who is responsible for scheduling its=
=20
resumption at some point. Coroutines TS is a suspend-up coroutine model:
the code responsible for scheduling its resumption is the code <i>inside</=
i> the coroutine, not necessarily its caller. If the code inside the corout=
ine suspends to the caller, that's because the particular coroutine cho=
oses to.<br><br>Generators
are the classic case of suspend-down. That's why your design works=20
especially well with them, and why the Coroutines TS works so poorly with=
=20
them. Continuations however are a classic case of suspend-up. This is=20
why your design requires lots of extra work to use them, while the=20
Coroutines TS makes it look like synchronous code.<br><br>Coroutines TS wil=
l never be as good at generators as your idea is. But neither will your ide=
a be as good at asynchronous code transformations as the Coroutines TS is.<=
br></div></div></blockquote><div><br></div></span><div>Again, the idea pres=
ented doesn't fundamentally change anything in current proposal with re=
spect to returned types (future/etc) or the way it suspends. All it does is=
exposes generated state machine class to every user, thus enabling certain=
options that designers may or may not take.</div><span class=3D""><div><br=
></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0=
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span=
><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=
=3D"gmail_quote"><div>Compiler can see that current coroutine calls another=
coroutine and generate required fluff automatically. You can introduce a n=
ew keyword (or convention) that will allow you to call coroutine in other w=
ay (but I doubt this need will be great).<br></div></div></div></div></bloc=
kquote></span><span><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div class=3D"gmail_quote"><div>- inlining of some of generated C++ objec=
t methods</div></div></div></blockquote></span><div><br>Inlining is only re=
levant when dealing with suspend-down style coroutines. That is, generators=
and the like. Inlining is not relevant (or possible) when dealing with sus=
pend-up continuations. This is why such inlining is an optimization to Coro=
utines TS rather than a requirement. It's a suspend-up model, so it doe=
s things in a suspend-up way.<br></div></div></blockquote><div><br></div></=
span><div>True, I was thinking about other methods given coroutine object m=
ay have. Maybe this would allow to avoid type erasure? I didn't think a=
bout it, tbh.</div><span class=3D""><div>=C2=A0</div><div><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div class=3D"gmail_quote"><span><div>I see... one o=
f the aims is to integrate coroutines with future/async stuff... I am proba=
bly behind on all this. All async libs I looked at used same approach -- pu=
blic API consists of a function (async_foo) that takes a callback. Then som=
eone somewhere cranks the event loop which eventually calls "process_e=
vents()" library function that in turn calls aforementioned callback.<=
br></div></span><span><div><br></div><div>So, for this library to add corou=
tine support you'd have to create second inline function (or macro) cor=
o_foo() that takes address of resume() method of current coroutine, registe=
rs it using async_foo() and suspends current coroutine. I.e. in this design=
you still have to add second version of your async_foo() -- a coroutine-aw=
are wrapper coro_foo(). I see no fault is this approach -- everything is cl=
ear and clean.</div><div><br></div><div>Now, if library instead exports &qu=
ot;future<int> foo()" -- there is no need for coro_foo(), but im=
plementation becomes less efficient and more complex. Because of type erasu=
res, having to allocate memory, having to move values and other stuff (like=
synchronization). Am I right? Is it a good price for not having to add a (=
rather simple) coro_foo()?<br></div></span></div></div></blockquote><div><b=
r>It all depends: is the person calling the async routine the one who actua=
lly has the continuation? The `future.then`-style interface allows anyone a=
t any time to hook a continuation into the process. Your `coro_foo` style r=
equires that the exact caller be the one who provides the continuation.<br>=
<br>And what if the continuation function itself needs a continuation? The =
caller has to provide that too. And what if the inner continuation needs to=
access something from the outer continuation? Well, you have to allocate t=
hat explicitly. And so forth.<br></div></div></blockquote><div><br></div></=
span><div>How often it will happen? Your typical caller of a coroutine is p=
robably another coroutine that awaits on it. In this case it works just fin=
e. In others -- related boilerplate can be buried into some utility functio=
n(s).</div><span class=3D""><div><br></div><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>`co_await`-style coding handles this =
with no manual intervention. Herb Sutter made a <a href=3D"https://channel9=
..msdn.com/events/Build/2013/2-306" target=3D"_blank">great presentation</a>=
a while back (skip ahead to around 51 minutes) on the failings of explicit=
callback-style continuations through lambdas and such, and demonstrated ho=
w use of `await` can make asynchronous code look exactly like synchronous c=
ode.<br><br>I'll reproduce his example here, in case you're unwilli=
ng to watch the video.<br></div></div></blockquote><div><br></div></span><d=
iv>Ok, now that was below the belt. I did watch it.</div><span class=3D""><=
div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div>Here's the synchronous code. It reads from a given filename, app=
ending `suffix` to each "chunk" in the file. It's based on on=
e of Microsoft's asynchronous file IO APIs (note that I've slightly=
adjusted some of the code):<br></div></div></blockquote><div>=C2=A0</div><=
/span><div><lots of snipping>=C2=A0<br></div><span class=3D""><div><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border=
-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>And your `coro=
_func` version would not work, due to the need of this code to continue its=
elf. You'd have to write a lambda, heap-allocate it, and do a bunch of =
other stuff to make the explicit continuation code work.<br></div></div></b=
lockquote><div><br></div></span><div>Why it wouldn't work? coro_foo() w=
ill end up calling async_foo() passing my current coroutine resume() as a c=
allback and suspending (i.e. returning). Code will be practically the same.=
I either fantastically missing something or we are not on the same page.</=
div><span class=3D""><div><br></div><div><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><div>The kind of design you've presented is <a href=3D=
"http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf" rel=3D"no=
follow" target=3D"_blank">exactly what the resumable expressions proposal u=
sed</a>. Only it was a bit cleverer about it, such that you would just have=
a resumable function called "await" that could be overloaded for=
some "awaitable" type, which would do the scheduling and unpacki=
ng, returning the unpacked value once resumed.=C2=A0</div></div></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br>You really shoul=
d look at that proposal; it's clearly what you want. And yes, it was lo=
oked at, but it didn't move forward past P0114R0.</div></div></blockquo=
te><div><br></div><div>Thank you, I will read it. But as I said -- it isn&#=
39;t what I was talking about.</div></div></div></div></blockquote></span><=
div><br>How can you say it isn't what you were talking about when you <=
i>haven't read it</i>?</div></div></blockquote><div><br></div></span><d=
iv>I meant I did not propose a new design -- I presented an idea (for curre=
nt design) that may change it a bit opening up some options.</div><div><br>=
</div></div>-- <br><div class=3D"m_2388235597506391563gmail_signature" data=
-smartmail=3D"gmail_signature">Sincerely yours,<br>Michael.</div>
</div></div><span class=3D"">
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1=
b-uACR2ygB0z1hDA3w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter" target=3D"_blank">https://groups.google.com/a/<wbr>isocpp.org/d/msgid/=
std-<wbr>proposals/CA%2BnLVP4wXQeo%<wbr>3DJsjMJybNfa9O3MxSQu1b-<wbr>uACR2yg=
B0z1hDA3w%40mail.gmail.<wbr>com</a>.<br>
</blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAJH_FNXr9GDvH92ZztR5iH7Xc8dy-%2BFL-_=
QFjFK3S1FQ%2BybJBg%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNXr9GDv=
H92ZztR5iH7Xc8dy-%2BFL-_QFjFK3S1FQ%2BybJBg%40mail.gmail.com</a>.<br />
--0000000000000283de0566fe268b--
.
Author: Lee Howes <xrikcus@gmail.com>
Date: Fri, 9 Mar 2018 09:33:21 -0800
Raw View
--0000000000004a865d0566fe309a
Content-Type: text/plain; charset="UTF-8"
Ok, enter sent the message. I wanted to also add:
> move coroutine declarions into separate TU and hide them behind plain
function.
but then I am back needing hooks like the coroutines TS provides - but
unlike the coroutines TS I don't see from your example what type that plain
function should return. So now, I wrap my coroutine in a free function foo.
something foo();
bar() {
await foo()? I'm not sure what the syntax would be here for awaiting on a
plain function... do I need a coroutine type defined here?
}
On 9 March 2018 at 09:30, Lee Howes <xrikcus@gmail.com> wrote:
> > coroutine void coro_bar(...) { ... }
> > class Foo {
> > virtual Awaitable bar() { return cb_(); }
> > coro_bar cb_; // an instance of state-machine class generated from
> coro_bar's definition
> > };
>
> > does it make sense? I didn't think about it this way, but it should
> probably work.
>
> You've added shared state. Now what happens if I want to do something like
> this:
>
> Foo f;
> thread t([&](){await f.bar());
> thread t2([&](){await f.bar());
> t.join();
> t2.join();
>
> I need two copies of cb_, or for cb_ to use heap allocation magic to hide
> that, or at the very least to synchronize the coroutine state.
>
> > It is the same problem as with templates.
>
> It certainly is. It is a huge problem.
> move coroutine declarions into separate TU and hide them behind plain
> function.
>
>
>
>
> On 9 March 2018 at 01:10, Michael Kilburn <crusader.mike@gmail.com> wrote:
>
>> On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
>>
>>> You are not being misunderstood. You're trying to equate all "stackless
>>> coroutine" proposals; you're claiming that they're all just minor
>>> variations of the same concept.
>>>
>>
>> No, I don't. But you correctly noted that some of existing proposals
>> already have "always visible" feature. That is ok -- I presented this idea
>> in context of current proposal in order to enable options of:
>> - manually controlling generated state machine object (allocation, etc)
>> to make heap elision optimization irrelevant
>> - changing convention -- e.g. use co_nowait instead of c_await (see my
>> answer to Todd)
>> - few others
>>
>> If you don't like any of these options -- naturally, that idea is a no
>> go. But maybe some of them can be appealing?
>>
>>
>> *They are not*. Coroutines TS is not just creating a resumable function;
>>> it's a lot more than that. It's implementing a specific model of
>>> coroutines, which is different from the model you're defining.
>>>
>>> If you want "just resumable functions", then you need to understand that
>>> this really is a completely different proposal with a completely different
>>> design from the Coroutines TS. It's not a slight modification of Coroutines
>>> TS (which is evidence in the fact that your design literally removes all of
>>> the Coroutines TS's keywords).
>>>
>>
>> keywords maybe removed but their intended effect stays unchanged.
>>
>>
>>
>>> Your design is a suspend-down coroutine model. When your kind of
>>> coroutine yields, it always returns to its nearest non-coroutine caller,
>>> who is responsible for scheduling its resumption at some point. Coroutines
>>> TS is a suspend-up coroutine model: the code responsible for scheduling its
>>> resumption is the code *inside* the coroutine, not necessarily its
>>> caller. If the code inside the coroutine suspends to the caller, that's
>>> because the particular coroutine chooses to.
>>>
>>> Generators are the classic case of suspend-down. That's why your design
>>> works especially well with them, and why the Coroutines TS works so poorly
>>> with them. Continuations however are a classic case of suspend-up. This is
>>> why your design requires lots of extra work to use them, while the
>>> Coroutines TS makes it look like synchronous code.
>>>
>>> Coroutines TS will never be as good at generators as your idea is. But
>>> neither will your idea be as good at asynchronous code transformations as
>>> the Coroutines TS is.
>>>
>>
>> Again, the idea presented doesn't fundamentally change anything in
>> current proposal with respect to returned types (future/etc) or the way it
>> suspends. All it does is exposes generated state machine class to every
>> user, thus enabling certain options that designers may or may not take.
>>
>>
>> Compiler can see that current coroutine calls another coroutine and
>>>> generate required fluff automatically. You can introduce a new keyword (or
>>>> convention) that will allow you to call coroutine in other way (but I doubt
>>>> this need will be great).
>>>>
>>> - inlining of some of generated C++ object methods
>>>>
>>>
>>> Inlining is only relevant when dealing with suspend-down style
>>> coroutines. That is, generators and the like. Inlining is not relevant (or
>>> possible) when dealing with suspend-up continuations. This is why such
>>> inlining is an optimization to Coroutines TS rather than a requirement.
>>> It's a suspend-up model, so it does things in a suspend-up way.
>>>
>>
>> True, I was thinking about other methods given coroutine object may have.
>> Maybe this would allow to avoid type erasure? I didn't think about it, tbh.
>>
>>
>> I see... one of the aims is to integrate coroutines with future/async
>>>> stuff... I am probably behind on all this. All async libs I looked at used
>>>> same approach -- public API consists of a function (async_foo) that takes a
>>>> callback. Then someone somewhere cranks the event loop which eventually
>>>> calls "process_events()" library function that in turn calls aforementioned
>>>> callback.
>>>>
>>>> So, for this library to add coroutine support you'd have to create
>>>> second inline function (or macro) coro_foo() that takes address of resume()
>>>> method of current coroutine, registers it using async_foo() and suspends
>>>> current coroutine. I.e. in this design you still have to add second version
>>>> of your async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fault
>>>> is this approach -- everything is clear and clean.
>>>>
>>>> Now, if library instead exports "future<int> foo()" -- there is no need
>>>> for coro_foo(), but implementation becomes less efficient and more complex.
>>>> Because of type erasures, having to allocate memory, having to move values
>>>> and other stuff (like synchronization). Am I right? Is it a good price for
>>>> not having to add a (rather simple) coro_foo()?
>>>>
>>>
>>> It all depends: is the person calling the async routine the one who
>>> actually has the continuation? The `future.then`-style interface allows
>>> anyone at any time to hook a continuation into the process. Your `coro_foo`
>>> style requires that the exact caller be the one who provides the
>>> continuation.
>>>
>>> And what if the continuation function itself needs a continuation? The
>>> caller has to provide that too. And what if the inner continuation needs to
>>> access something from the outer continuation? Well, you have to allocate
>>> that explicitly. And so forth.
>>>
>>
>> How often it will happen? Your typical caller of a coroutine is probably
>> another coroutine that awaits on it. In this case it works just fine. In
>> others -- related boilerplate can be buried into some utility function(s).
>>
>>
>>
>>> `co_await`-style coding handles this with no manual intervention. Herb
>>> Sutter made a great presentation
>>> <https://channel9.msdn.com/events/Build/2013/2-306> a while back (skip
>>> ahead to around 51 minutes) on the failings of explicit callback-style
>>> continuations through lambdas and such, and demonstrated how use of `await`
>>> can make asynchronous code look exactly like synchronous code.
>>>
>>> I'll reproduce his example here, in case you're unwilling to watch the
>>> video.
>>>
>>
>> Ok, now that was below the belt. I did watch it.
>>
>>
>> Here's the synchronous code. It reads from a given filename, appending
>>> `suffix` to each "chunk" in the file. It's based on one of Microsoft's
>>> asynchronous file IO APIs (note that I've slightly adjusted some of the
>>> code):
>>>
>>
>> <lots of snipping>
>>
>> And your `coro_func` version would not work, due to the need of this code
>>> to continue itself. You'd have to write a lambda, heap-allocate it, and do
>>> a bunch of other stuff to make the explicit continuation code work.
>>>
>>
>> Why it wouldn't work? coro_foo() will end up calling async_foo() passing
>> my current coroutine resume() as a callback and suspending (i.e.
>> returning). Code will be practically the same. I either fantastically
>> missing something or we are not on the same page.
>>
>>
>> The kind of design you've presented is exactly what the resumable
>>>>> expressions proposal used
>>>>> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>.
>>>>> Only it was a bit cleverer about it, such that you would just have a
>>>>> resumable function called "await" that could be overloaded for some
>>>>> "awaitable" type, which would do the scheduling and unpacking, returning
>>>>> the unpacked value once resumed.
>>>>>
>>>>
>>>>> You really should look at that proposal; it's clearly what you want.
>>>>> And yes, it was looked at, but it didn't move forward past P0114R0.
>>>>>
>>>>
>>>> Thank you, I will read it. But as I said -- it isn't what I was talking
>>>> about.
>>>>
>>>
>>> How can you say it isn't what you were talking about when you *haven't
>>> read it*?
>>>
>>
>> I meant I did not propose a new design -- I presented an idea (for
>> current design) that may change it a bit opening up some options.
>>
>> --
>> Sincerely yours,
>> Michael.
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> To view this discussion on the web visit https://groups.google.com/a/is
>> ocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9
>> O3MxSQu1b-uACR2ygB0z1hDA3w%40mail.gmail.com
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1b-uACR2ygB0z1hDA3w%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
>
>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNUAPYXcvr69yB9oGYq0GDqQ_zPkv5PvAuksYrWPBO30nA%40mail.gmail.com.
--0000000000004a865d0566fe309a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Ok, enter sent the message. I wanted to also add:<div><br>=
</div><div><span style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;=
font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-varia=
nt-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgrou=
nd-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-col=
or:initial;float:none;display:inline">> move coroutine declarions into s=
eparate TU and hide them behind plain function.</span><br></div><div><span =
style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;=
font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;fo=
nt-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-t=
ransform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,=
255,255);text-decoration-style:initial;text-decoration-color:initial;float:=
none;display:inline"><br></span></div><div><span style=3D"color:rgb(34,34,3=
4);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-var=
iant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spaci=
ng:normal;text-align:start;text-indent:0px;text-transform:none;white-space:=
normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-s=
tyle:initial;text-decoration-color:initial;float:none;display:inline">but t=
hen I am back needing hooks like the coroutines TS provides - but unlike th=
e coroutines TS I don't see from your example what type that plain func=
tion should return. So now, I wrap my coroutine in a free function foo.</sp=
an></div><div><br></div><div><span style=3D"font-size:12.8px">something foo=
();</span></div><div><span style=3D"font-size:12.8px"><br></span></div><div=
><span style=3D"font-size:12.8px">bar() {</span></div><div><span style=3D"f=
ont-size:12.8px">=C2=A0 await foo()? I'm not sure what the syntax would=
be here for awaiting on a plain function... do I need a coroutine type def=
ined here?=C2=A0</span></div><div><span style=3D"font-size:12.8px">}</span>=
</div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On 9 =
March 2018 at 09:30, Lee Howes <span dir=3D"ltr"><<a href=3D"mailto:xrik=
cus@gmail.com" target=3D"_blank">xrikcus@gmail.com</a>></span> wrote:<br=
><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""><div styl=
e=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font=
-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-w=
eight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-trans=
form:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,=
255);text-decoration-style:initial;text-decoration-color:initial">> coro=
utine void coro_bar(...) { ... }</div><div style=3D"color:rgb(34,34,34);fon=
t-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-l=
igatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:i=
nitial;text-decoration-color:initial"><span style=3D"font-size:12.8px">>=
class Foo {</span><br></div><div style=3D"color:rgb(34,34,34);font-family:=
arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;te=
xt-decoration-color:initial"><div style=3D"color:rgb(34,34,34);font-family:=
arial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-varia=
nt-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-dec=
oration-style:initial;text-decoration-color:initial;font-size:12.8px;backgr=
ound-color:rgb(255,255,255)">>=C2=A0 =C2=A0virtual Awaitable bar() { ret=
urn cb_(); }</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-=
serif;font-style:normal;font-variant-ligatures:normal;font-variant-caps:nor=
mal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;=
text-transform:none;white-space:normal;word-spacing:0px;text-decoration-sty=
le:initial;text-decoration-color:initial;font-size:12.8px;background-color:=
rgb(255,255,255)">>=C2=A0 =C2=A0 =C2=A0coro_bar cb_;=C2=A0 // an instanc=
e of state-machine class generated from coro_bar's definition</div><div=
style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-style:norma=
l;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;le=
tter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;wh=
ite-space:normal;word-spacing:0px;text-decoration-style:initial;text-decora=
tion-color:initial;font-size:12.8px;background-color:rgb(255,255,255)">>=
};</div><br></div><div style=3D"color:rgb(34,34,34);font-family:arial,sans=
-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;fon=
t-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:star=
t;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;b=
ackground-color:rgb(255,255,255);text-decoration-style:initial;text-decorat=
ion-color:initial">> does it make sense? I didn't think about it thi=
s way, but it should probably work.</div></span><span class=3D"m_7570799115=
696749087gmail-im" style=3D"color:rgb(80,0,80);font-family:arial,sans-serif=
;font-size:12.8px;font-style:normal;font-variant-ligatures:normal;font-vari=
ant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text=
-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgro=
und-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-co=
lor:initial"><div><span class=3D"m_7570799115696749087gmail-im" style=3D"co=
lor:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;font-style:n=
ormal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:40=
0;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:non=
e;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);tex=
t-decoration-style:initial;text-decoration-color:initial"><br></span></div>=
You've added shared state. Now what happens if I want to do something l=
ike this:</span><div><br></div><div>Foo f;</div><div>thread t([&](){awa=
it=C2=A0 f.bar());</div><div><span style=3D"color:rgb(34,34,34);font-family=
:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;te=
xt-decoration-color:initial;float:none;display:inline">thread t2([&](){=
await=C2=A0 f.bar());</span><br></div><div>t.join();</div><div>t2.join();</=
div><div><br></div><div>I need two copies of cb_, or for cb_ to use heap al=
location magic to hide that, or at the very least to synchronize the corout=
ine state.</div><span class=3D""><div><br></div><div>>=C2=A0<span style=
=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8px;font-=
style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-we=
ight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transf=
orm:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,2=
55);text-decoration-style:initial;text-decoration-color:initial;float:none;=
display:inline"><span>=C2=A0</span>It is the same problem as with templates=
..=C2=A0</span></div><div><span style=3D"font-size:12.8px"><br></span></div>=
</span><div><span style=3D"font-size:12.8px">It certainly is. It is a huge =
problem.</span></div><span class=3D""><div><span style=3D"font-size:12.8px"=
>move coroutine declarions into separate TU and hide them behind plain func=
tion.</span><br><br class=3D"m_7570799115696749087gmail-Apple-interchange-n=
ewline"></div><div><br></div><div><br></div></span></div><div class=3D"HOEn=
Zb"><div class=3D"h5"><div class=3D"gmail_extra"><br><div class=3D"gmail_qu=
ote">On 9 March 2018 at 01:10, Michael Kilburn <span dir=3D"ltr"><<a hre=
f=3D"mailto:crusader.mike@gmail.com" target=3D"_blank">crusader.mike@gmail.=
com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><span>On Thu, Mar 8=
, 2018 at 11:12 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmc=
kesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>You are not bein=
g misunderstood. You're trying to equate all "stackless=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br></div></div></blockquote><div><br></=
div></span><div>No, I don't. But you correctly noted that some of exist=
ing proposals already have "always visible" feature. That is ok -=
- I presented this idea in context of current proposal in order to enable o=
ptions of:</div><div>- manually controlling generated state machine object =
(allocation, etc) to make heap elision optimization irrelevant</div><div>- =
changing convention -- e.g. use co_nowait instead of c_await (see my answer=
to Todd)</div><div>- few others</div><div><br></div><div>If you don't =
like any of these options -- naturally, that idea is a no go. But maybe som=
e of them can be appealing?</div><span><div><br></div><div><br></div><block=
quote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div><i>They are not</i>. Corouti=
nes TS is not just creating a resumable function; it's a lot more than =
that. It's implementing a specific model of coroutines, which is differ=
ent from the model you're defining.<br><br>If you want "just resum=
able functions", then you need to understand that this really is a com=
pletely different proposal with a completely different design from the Coro=
utines TS. It's not a slight modification of Coroutines TS (which is ev=
idence in the fact that your design literally removes all of the Coroutines=
TS's keywords).<br></div></div></blockquote><div><br></div></span><div=
>keywords maybe removed but their intended effect stays unchanged.</div><sp=
an><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Your design is a=20
suspend-down coroutine model. When your kind of coroutine yields, it always=
returns
to its nearest non-coroutine caller, who is responsible for scheduling its=
=20
resumption at some point. Coroutines TS is a suspend-up coroutine model:
the code responsible for scheduling its resumption is the code <i>inside</=
i> the coroutine, not necessarily its caller. If the code inside the corout=
ine suspends to the caller, that's because the particular coroutine cho=
oses to.<br><br>Generators
are the classic case of suspend-down. That's why your design works=20
especially well with them, and why the Coroutines TS works so poorly with=
=20
them. Continuations however are a classic case of suspend-up. This is=20
why your design requires lots of extra work to use them, while the=20
Coroutines TS makes it look like synchronous code.<br><br>Coroutines TS wil=
l never be as good at generators as your idea is. But neither will your ide=
a be as good at asynchronous code transformations as the Coroutines TS is.<=
br></div></div></blockquote><div><br></div></span><div>Again, the idea pres=
ented doesn't fundamentally change anything in current proposal with re=
spect to returned types (future/etc) or the way it suspends. All it does is=
exposes generated state machine class to every user, thus enabling certain=
options that designers may or may not take.</div><span><div><br></div><div=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quo=
te"><div>Compiler can see that current coroutine calls another coroutine an=
d generate required fluff automatically. You can introduce a new keyword (o=
r convention) that will allow you to call coroutine in other way (but I dou=
bt this need will be great).<br></div></div></div></div></blockquote></span=
><span><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=
=3D"gmail_quote"><div>- inlining of some of generated C++ object methods</d=
iv></div></div></blockquote></span><div><br>Inlining is only relevant when =
dealing with suspend-down style coroutines. That is, generators and the lik=
e. Inlining is not relevant (or possible) when dealing with suspend-up cont=
inuations. This is why such inlining is an optimization to Coroutines TS ra=
ther than a requirement. It's a suspend-up model, so it does things in =
a suspend-up way.<br></div></div></blockquote><div><br></div></span><div>Tr=
ue, I was thinking about other methods given coroutine object may have. May=
be this would allow to avoid type erasure? I didn't think about it, tbh=
..</div><span><div>=C2=A0</div><div><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div class=3D"gmail_quote"><span><div>I see... one of the aims is to integr=
ate coroutines with future/async stuff... I am probably behind on all this.=
All async libs I looked at used same approach -- public API consists of a =
function (async_foo) that takes a callback. Then someone somewhere cranks t=
he event loop which eventually calls "process_events()" library f=
unction that in turn calls aforementioned callback.<br></div></span><span><=
div><br></div><div>So, for this library to add coroutine support you'd =
have to create second inline function (or macro) coro_foo() that takes addr=
ess of resume() method of current coroutine, registers it using async_foo()=
and suspends current coroutine. I.e. in this design you still have to add =
second version of your async_foo() -- a coroutine-aware wrapper coro_foo().=
I see no fault is this approach -- everything is clear and clean.</div><di=
v><br></div><div>Now, if library instead exports "future<int> fo=
o()" -- there is no need for coro_foo(), but implementation becomes le=
ss efficient and more complex. Because of type erasures, having to allocate=
memory, having to move values and other stuff (like synchronization). Am I=
right? Is it a good price for not having to add a (rather simple) coro_foo=
()?<br></div></span></div></div></blockquote><div><br>It all depends: is th=
e person calling the async routine the one who actually has the continuatio=
n? The `future.then`-style interface allows anyone at any time to hook a co=
ntinuation into the process. Your `coro_foo` style requires that the exact =
caller be the one who provides the continuation.<br><br>And what if the con=
tinuation function itself needs a continuation? The caller has to provide t=
hat too. And what if the inner continuation needs to access something from =
the outer continuation? Well, you have to allocate that explicitly. And so =
forth.<br></div></div></blockquote><div><br></div></span><div>How often it =
will happen? Your typical caller of a coroutine is probably another corouti=
ne that awaits on it. In this case it works just fine. In others -- related=
boilerplate can be buried into some utility function(s).</div><span><div><=
br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin=
:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><=
div>`co_await`-style coding handles this with no manual intervention. Herb =
Sutter made a <a href=3D"https://channel9.msdn.com/events/Build/2013/2-306"=
target=3D"_blank">great presentation</a> a while back (skip ahead to aroun=
d 51 minutes) on the failings of explicit callback-style continuations thro=
ugh lambdas and such, and demonstrated how use of `await` can make asynchro=
nous code look exactly like synchronous code.<br><br>I'll reproduce his=
example here, in case you're unwilling to watch the video.<br></div></=
div></blockquote><div><br></div></span><div>Ok, now that was below the belt=
.. I did watch it.</div><span><div><br></div><div><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div>Here's the synchronous code. It re=
ads from a given filename, appending `suffix` to each "chunk" in =
the file. It's based on one of Microsoft's asynchronous file IO API=
s (note that I've slightly adjusted some of the code):<br></div></div><=
/blockquote><div>=C2=A0</div></span><div><lots of snipping>=C2=A0<br>=
</div><span><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<div>And your `coro_func` version would not work, due to the need of this c=
ode to continue itself. You'd have to write a lambda, heap-allocate it,=
and do a bunch of other stuff to make the explicit continuation code work.=
<br></div></div></blockquote><div><br></div></span><div>Why it wouldn't=
work? coro_foo() will end up calling async_foo() passing my current corout=
ine resume() as a callback and suspending (i.e. returning). Code will be pr=
actically the same. I either fantastically missing something or we are not =
on the same page.</div><span><div><br></div><div><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><span><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gm=
ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>The kind of design you've presented is <a=
href=3D"http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf" r=
el=3D"nofollow" target=3D"_blank">exactly what the resumable expressions pr=
oposal used</a>. Only it was a bit cleverer about it, such that you would j=
ust have a resumable function called "await" that could be overlo=
aded for some "awaitable" type, which would do the scheduling and=
unpacking, returning the unpacked value once resumed.=C2=A0</div></div></b=
lockquote><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br>You real=
ly should look at that proposal; it's clearly what you want. And yes, i=
t was looked at, but it didn't move forward past P0114R0.</div></div></=
blockquote><div><br></div><div>Thank you, I will read it. But as I said -- =
it isn't what I was talking about.</div></div></div></div></blockquote>=
</span><div><br>How can you say it isn't what you were talking about wh=
en you <i>haven't read it</i>?</div></div></blockquote><div><br></div><=
/span><div>I meant I did not propose a new design -- I presented an idea (f=
or current design) that may change it a bit opening up some options.</div><=
div><br></div></div>-- <br><div class=3D"m_7570799115696749087m_23882355975=
06391563gmail_signature" data-smartmail=3D"gmail_signature">Sincerely yours=
,<br>Michael.</div>
</div></div><span>
<p></p>
-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isoc<wbr>pp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4wXQeo%3DJsjMJybNfa9O3MxSQu1=
b-uACR2ygB0z1hDA3w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoo=
ter" target=3D"_blank">https://groups.google.com/a/is<wbr>ocpp.org/d/msgid/=
std-proposals<wbr>/CA%2BnLVP4wXQeo%3DJsjMJybNfa9<wbr>O3MxSQu1b-uACR2ygB0z1h=
DA3w%<wbr>40mail.gmail.com</a>.<br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CAJH_FNUAPYXcvr69yB9oGYq0GDqQ_zPkv5Pv=
AuksYrWPBO30nA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAJH_FNUAPYXcvr69=
yB9oGYq0GDqQ_zPkv5PvAuksYrWPBO30nA%40mail.gmail.com</a>.<br />
--0000000000004a865d0566fe309a--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 9 Mar 2018 09:38:20 -0800 (PST)
Raw View
------=_Part_5653_1841043181.1520617100176
Content-Type: multipart/alternative;
boundary="----=_Part_5654_1756084715.1520617100177"
------=_Part_5654_1756084715.1520617100177
Content-Type: text/plain; charset="UTF-8"
On Friday, March 9, 2018 at 4:10:36 AM UTC-5, Michael Kilburn wrote:
>
> On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> You are not being misunderstood. You're trying to equate all "stackless
>> coroutine" proposals; you're claiming that they're all just minor
>> variations of the same concept.
>>
>
> No, I don't. But you correctly noted that some of existing proposals
> already have "always visible" feature. That is ok -- I presented this idea
> in context of current proposal in order to enable options of:
> - manually controlling generated state machine object (allocation, etc) to
> make heap elision optimization irrelevant
> - changing convention -- e.g. use co_nowait instead of c_await (see my
> answer to Todd)
> - few others
>
> If you don't like any of these options -- naturally, that idea is a no go.
> But maybe some of them can be appealing?
>
It's not a question of liking or disliking the options. These options are
irrelevant for the use cases that the Coroutines TS is intended to work
with. They force the system to move away from the optimal syntax for
suspend-up-style programming and towards a suspend-down model.
The basic concepts you're describing are appealing; I implore you to read
P0114. But they are not appropriate *for this proposal*. Your idea is
trying to turn a suspend-up system into a suspend-down one.
*They are not*. Coroutines TS is not just creating a resumable function;
>> it's a lot more than that. It's implementing a specific model of
>> coroutines, which is different from the model you're defining.
>>
>> If you want "just resumable functions", then you need to understand that
>> this really is a completely different proposal with a completely different
>> design from the Coroutines TS. It's not a slight modification of Coroutines
>> TS (which is evidence in the fact that your design literally removes all of
>> the Coroutines TS's keywords).
>>
>
> keywords maybe removed but their intended effect stays unchanged.
>
How can something which no longer exist have an effect?
For example, how does one of your coroutines yield values? What's funny is
that, since I've read P0114, I have a pretty good idea what your answer
will be ;)
Your design is a suspend-down coroutine model. When your kind of coroutine
>> yields, it always returns to its nearest non-coroutine caller, who is
>> responsible for scheduling its resumption at some point. Coroutines TS is a
>> suspend-up coroutine model: the code responsible for scheduling its
>> resumption is the code *inside* the coroutine, not necessarily its
>> caller. If the code inside the coroutine suspends to the caller, that's
>> because the particular coroutine chooses to.
>>
>> Generators are the classic case of suspend-down. That's why your design
>> works especially well with them, and why the Coroutines TS works so poorly
>> with them. Continuations however are a classic case of suspend-up. This is
>> why your design requires lots of extra work to use them, while the
>> Coroutines TS makes it look like synchronous code.
>>
>> Coroutines TS will never be as good at generators as your idea is. But
>> neither will your idea be as good at asynchronous code transformations as
>> the Coroutines TS is.
>>
>
> Again, the idea presented doesn't fundamentally change anything in current
> proposal with respect to returned types (future/etc) or the way it
> suspends. All it does is exposes generated state machine class to every
> user, thus enabling certain options that designers may or may not take.
>
And by forcing every user to have to interact with such state (even if that
interaction is just to pass it to a utility function), it makes it more
difficult to deal with suspend-up programming.
I see... one of the aims is to integrate coroutines with future/async
>>> stuff... I am probably behind on all this. All async libs I looked at used
>>> same approach -- public API consists of a function (async_foo) that takes a
>>> callback. Then someone somewhere cranks the event loop which eventually
>>> calls "process_events()" library function that in turn calls aforementioned
>>> callback.
>>>
>>> So, for this library to add coroutine support you'd have to create
>>> second inline function (or macro) coro_foo() that takes address of resume()
>>> method of current coroutine, registers it using async_foo() and suspends
>>> current coroutine. I.e. in this design you still have to add second version
>>> of your async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fault
>>> is this approach -- everything is clear and clean.
>>>
>>> Now, if library instead exports "future<int> foo()" -- there is no need
>>> for coro_foo(), but implementation becomes less efficient and more complex.
>>> Because of type erasures, having to allocate memory, having to move values
>>> and other stuff (like synchronization). Am I right? Is it a good price for
>>> not having to add a (rather simple) coro_foo()?
>>>
>>
>> It all depends: is the person calling the async routine the one who
>> actually has the continuation? The `future.then`-style interface allows
>> anyone at any time to hook a continuation into the process. Your `coro_foo`
>> style requires that the exact caller be the one who provides the
>> continuation.
>>
>> And what if the continuation function itself needs a continuation? The
>> caller has to provide that too. And what if the inner continuation needs to
>> access something from the outer continuation? Well, you have to allocate
>> that explicitly. And so forth.
>>
>
> How often it will happen?
>
Then-style continuations have flexibility as a big part of their design.
You're not required to put all continuations in a single call graph. You
can pass `future`s or whatever to whomever wants to add to them, and they
can add as many functions as they like, mutating the value with each added
functor.
This happens as often as the user wants it to happen. It is not your place
to interfere in that.
Your typical caller of a coroutine is probably another coroutine that
> awaits on it. In this case it works just fine. In others -- related
> boilerplate can be buried into some utility function(s).
>
Please read P0114; everything you just said is almost *exactly* what it
says. A keyword to prevent awaiting on a coroutine within a coroutine. A
keyword to explicitly declare a function to be resumable/coroutine. Having
to use utility function(s) to support suspend-up programming. All of these
are core aspects of P0114.
You're just using different words, but the design you've come up with is
the same. And that's important because that design is very much not a minor
change to Coroutines TS.
`co_await`-style coding handles this with no manual intervention. Herb
>> Sutter made a great presentation
>> <https://channel9.msdn.com/events/Build/2013/2-306> a while back (skip
>> ahead to around 51 minutes) on the failings of explicit callback-style
>> continuations through lambdas and such, and demonstrated how use of `await`
>> can make asynchronous code look exactly like synchronous code.
>>
>> I'll reproduce his example here, in case you're unwilling to watch the
>> video.
>>
>
> Ok, now that was below the belt. I did watch it.
>
>
> Here's the synchronous code. It reads from a given filename, appending
>> `suffix` to each "chunk" in the file. It's based on one of Microsoft's
>> asynchronous file IO APIs (note that I've slightly adjusted some of the
>> code):
>>
>
> <lots of snipping>
>
> And your `coro_func` version would not work, due to the need of this code
>> to continue itself. You'd have to write a lambda, heap-allocate it, and do
>> a bunch of other stuff to make the explicit continuation code work.
>>
>
> Why it wouldn't work? coro_foo() will end up calling async_foo() passing
> my current coroutine resume() as a callback and suspending (i.e.
> returning). Code will be practically the same. I either fantastically
> missing something or we are not on the same page.
>
Show me how the code would "be practically the same". Present the
equivalent code using your idea.
And please note that it must be the *equivalent code*: based on `.then`
style continuations and the like. So the return value still needs to be a
`task<string>`. And the function itself must be a regular function (and
thus cannot directly use your `coroutine` keyword).
The kind of design you've presented is exactly what the resumable
>>>> expressions proposal used
>>>> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>.
>>>> Only it was a bit cleverer about it, such that you would just have a
>>>> resumable function called "await" that could be overloaded for some
>>>> "awaitable" type, which would do the scheduling and unpacking, returning
>>>> the unpacked value once resumed.
>>>>
>>>
>>>> You really should look at that proposal; it's clearly what you want.
>>>> And yes, it was looked at, but it didn't move forward past P0114R0.
>>>>
>>>
>>> Thank you, I will read it. But as I said -- it isn't what I was talking
>>> about.
>>>
>>
>> How can you say it isn't what you were talking about when you *haven't
>> read it*?
>>
>
> I meant I did not propose a new design -- I presented an idea (for current
> design) that may change it a bit opening up some options.
>
You keep saying that it's not a new design, and yet all evidence says that
it is. Here are a number of aspects of the design of Coroutines TS:
1. Coroutines appear to be regular functions using a regular interface.
Function overloading works as normal with them.
2. Coroutines have a built-in and hidden state object with an internal
return value object.
3. The internal functor that represents a coroutine is only visible to the
code that absolutely needs to know it exists: the code which schedules its
resumption.
4. The scheduling of the resumption of the coroutine is done entirely from
within the coroutine itself. It may delegate this to the caller, but this
is something it must explicitly choose to do.
5. There is direct and *effortless* support for suspend-up via the
`co_await` operator and its associated machinery.
I would say that most of these are *fundamental* aspects of what makes the
Coroutines TS what it is. Here is how your design compares:
1. Coroutines are not regular functions. You haven't explained how function
overloading works with coroutines.
2. Coroutines do not have built-in and hidden state objects; they directly
expose this state to the code talking about them.
3. The code calling a coroutine must interact with the internal functor
that represents a coroutine.
4. Scheduling the resumption of the coroutine is always granted to the
caller.
5. Suspend-up requires explicit effort from the caller. There is apparently
no `co_await` operator at all.
It's not even clear if your system allows the user to create their own
promise/future types. Coroutines TS allows this by default; the coroutine
machinery inspects the coroutine function's signature to determine what the
internal promise object will be (if your return value is std::future<T>,
the promise type would be std::promise<T>). Yours seems to require the
caller to decide what kind of promise/future will be used. So there's
another difference.
How can you say that these changes do not constitute a "new design" (and,
as I keep reminding you, your design is almost *exactly* P0114)? You're not
making a minor tweak to an existing propsoal; you're fundamentally changing
it. You even seem to understand that when you agreed with Todd's analogy
with lambdas. An "always type-erased" lambda is very much a new design
compared to a "not type-erased" lambda. They may do similar things, but
they do them in a fundamentally different way.
To you and your use cases, this may not seem like a big change. But every
use case you've presented is for suspend-down, not for suspend-up style
coding. And suspend-up is what the Coroutines TS is all about.
So this very much is a new design.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/331fb2e5-be21-4795-b73e-396fb39ccf24%40isocpp.org.
------=_Part_5654_1756084715.1520617100177
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, March 9, 2018 at 4:10:36 AM UTC-5, Michael Kilb=
urn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v><div class=3D"gmail_quote">On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <=
span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscat=
ed-mailto=3D"SOzVLTWMBAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
;javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;;return true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div>You are not being misunderstood. You&#=
39;re trying to equate all "stackless=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br></div></div></blockquote><div><br></=
div><div>No, I don't. But you correctly noted that some of existing pro=
posals already have "always visible" feature. That is ok -- I pre=
sented this idea in context of current proposal in order to enable options =
of:</div><div>- manually controlling generated state machine object (alloca=
tion, etc) to make heap elision optimization irrelevant</div><div>- changin=
g convention -- e.g. use co_nowait instead of c_await (see my answer to Tod=
d)</div><div>- few others</div><div><br></div><div>If you don't like an=
y of these options -- naturally, that idea is a no go. But maybe some of th=
em can be appealing?</div></div></div></div></blockquote><div><br>It's =
not a question of liking or disliking the options. These options are irrele=
vant for the use cases that the Coroutines TS is intended to work with. The=
y force the system to move away from the optimal syntax for suspend-up-styl=
e programming and towards a suspend-down model.<br><br>The basic concepts y=
ou're describing are appealing; I implore you to read P0114. But they a=
re not appropriate <i>for this proposal</i>. Your idea is trying to turn a =
suspend-up system into a suspend-down one.<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote=
"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><i>They a=
re not</i>. Coroutines TS is not just creating a resumable function; it'=
;s a lot more than that. It's implementing a specific model of coroutin=
es, which is different from the model you're defining.<br><br>If you wa=
nt "just resumable functions", then you need to understand that t=
his really is a completely different proposal with a completely different d=
esign from the Coroutines TS. It's not a slight modification of Corouti=
nes TS (which is evidence in the fact that your design literally removes al=
l of the Coroutines TS's keywords).<br></div></div></blockquote><div><b=
r></div><div>keywords maybe removed but their intended effect stays unchang=
ed.</div></div></div></div></blockquote><div><br>How can something which no=
longer exist have an effect?<br><br>For example, how does one of your coro=
utines yield values? What's funny is that, since I've read P0114, I=
have a pretty good idea what your answer will be ;)<br><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Y=
our design is a=20
suspend-down coroutine model. When your kind of coroutine yields, it always=
returns
to its nearest non-coroutine caller, who is responsible for scheduling its=
=20
resumption at some point. Coroutines TS is a suspend-up coroutine model:
the code responsible for scheduling its resumption is the code <i>inside</=
i> the coroutine, not necessarily its caller. If the code inside the corout=
ine suspends to the caller, that's because the particular coroutine cho=
oses to.<br><br>Generators
are the classic case of suspend-down. That's why your design works=20
especially well with them, and why the Coroutines TS works so poorly with=
=20
them. Continuations however are a classic case of suspend-up. This is=20
why your design requires lots of extra work to use them, while the=20
Coroutines TS makes it look like synchronous code.<br><br>Coroutines TS wil=
l never be as good at generators as your idea is. But neither will your ide=
a be as good at asynchronous code transformations as the Coroutines TS is.<=
br></div></div></blockquote><div><br></div><div>Again, the idea presented d=
oesn't fundamentally change anything in current proposal with respect t=
o returned types (future/etc) or the way it suspends. All it does is expose=
s generated state machine class to every user, thus enabling certain option=
s that designers may or may not take.</div></div></div></div></blockquote><=
div><br>And by forcing every user to have to interact with such state (even=
if that interaction is just to pass it to a utility function), it makes it=
more difficult to deal with suspend-up programming.<br><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><div></div><div></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div class=3D=
"gmail_quote"><span><div>I see... one of the aims is to integrate coroutine=
s with future/async stuff... I am probably behind on all this. All async li=
bs I looked at used same approach -- public API consists of a function (asy=
nc_foo) that takes a callback. Then someone somewhere cranks the event loop=
which eventually calls "process_events()" library function that =
in turn calls aforementioned callback.<br></div></span><span><div><br></div=
><div>So, for this library to add coroutine support you'd have to creat=
e second inline function (or macro) coro_foo() that takes address of resume=
() method of current coroutine, registers it using async_foo() and suspends=
current coroutine. I.e. in this design you still have to add second versio=
n of your async_foo() -- a coroutine-aware wrapper coro_foo(). I see no fau=
lt is this approach -- everything is clear and clean.</div><div><br></div><=
div>Now, if library instead exports "future<int> foo()" -- =
there is no need for coro_foo(), but implementation becomes less efficient =
and more complex. Because of type erasures, having to allocate memory, havi=
ng to move values and other stuff (like synchronization). Am I right? Is it=
a good price for not having to add a (rather simple) coro_foo()?<br></div>=
</span></div></div></blockquote><div><br>It all depends: is the person call=
ing the async routine the one who actually has the continuation? The `futur=
e.then`-style interface allows anyone at any time to hook a continuation in=
to the process. Your `coro_foo` style requires that the exact caller be the=
one who provides the continuation.<br><br>And what if the continuation fun=
ction itself needs a continuation? The caller has to provide that too. And =
what if the inner continuation needs to access something from the outer con=
tinuation? Well, you have to allocate that explicitly. And so forth.<br></d=
iv></div></blockquote><div><br></div><div>How often it will happen?</div></=
div></div></div></blockquote><div><br>Then-style continuations have flexibi=
lity as a big part of their design. You're not required to put all cont=
inuations in a single call graph. You can pass `future`s or whatever to who=
mever wants to add to them, and they can add as many functions as they like=
, mutating the value with each added functor.<br><br>This happens as often =
as the user wants it to happen. It is not your place to interfere in that.<=
br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div class=3D"gmail_quote"><div> Your typical caller of a coroutine is=
probably another coroutine that awaits on it. In this case it works just f=
ine. In others -- related boilerplate can be buried into some utility funct=
ion(s).</div></div></div></div></blockquote><div><br>Please read P0114; eve=
rything you just said is almost <i>exactly</i> what it says. A keyword to p=
revent awaiting on a coroutine within a coroutine. A keyword to explicitly =
declare a function to be resumable/coroutine. Having to use utility functio=
n(s) to support suspend-up programming. All of these are core aspects of P0=
114.<br><br>You're just using different words, but the design you'v=
e come up with is the same. And that's important because that design is=
very much not a minor change to Coroutines TS.<br><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_qu=
ote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>`co_aw=
ait`-style coding handles this with no manual intervention. Herb Sutter mad=
e a <a href=3D"https://channel9.msdn.com/events/Build/2013/2-306" target=3D=
"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https://www.googl=
e.com/url?q\x3dhttps%3A%2F%2Fchannel9.msdn.com%2Fevents%2FBuild%2F2013%2F2-=
306\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG_4CUrf4qpurGLd6RMoIWHCUGHmQ=
9;;return true;" onclick=3D"this.href=3D'https://www.google.com/url?q\x=
3dhttps%3A%2F%2Fchannel9.msdn.com%2Fevents%2FBuild%2F2013%2F2-306\x26sa\x3d=
D\x26sntz\x3d1\x26usg\x3dAFQjCNG_4CUrf4qpurGLd6RMoIWHCUGHmQ';return tru=
e;">great presentation</a> a while back (skip ahead to around 51 minutes) o=
n the failings of explicit callback-style continuations through lambdas and=
such, and demonstrated how use of `await` can make asynchronous code look =
exactly like synchronous code.<br><br>I'll reproduce his example here, =
in case you're unwilling to watch the video.<br></div></div></blockquot=
e><div><br></div><div>Ok, now that was below the belt. I did watch it.</div=
><div><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div>Here's the synchronous code. It reads from a given filename, a=
ppending `suffix` to each "chunk" in the file. It's based on =
one of Microsoft's asynchronous file IO APIs (note that I've slight=
ly adjusted some of the code):<br></div></div></blockquote><div>=C2=A0</div=
><div><lots of snipping>=C2=A0<br></div><div><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>And your `coro_func` version would n=
ot work, due to the need of this code to continue itself. You'd have to=
write a lambda, heap-allocate it, and do a bunch of other stuff to make th=
e explicit continuation code work.<br></div></div></blockquote><div><br></d=
iv><div>Why it wouldn't work? coro_foo() will end up calling async_foo(=
) passing my current coroutine resume() as a callback and suspending (i.e. =
returning). Code will be practically the same. I either fantastically missi=
ng something or we are not on the same page.</div></div></div></div></block=
quote><div><br>Show me how the code would "be practically the same&quo=
t;. Present the equivalent code using your idea.<br><br>And please note tha=
t it must be the <i>equivalent code</i>: based on `.then` style continuatio=
ns and the like. So the return value still needs to be a `task<string>=
;`. And the function itself must be a regular function (and thus cannot dir=
ectly use your `coroutine` keyword).<br><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><=
/div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The kind of design you&#=
39;ve presented is <a href=3D"http://open-std.org/JTC1/SC22/WG21/docs/paper=
s/2015/p0114r0.pdf" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.=
href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fopen-std.org%2FJTC1=
%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0114r0.pdf\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHiqyTXibcdjweNAkVM9dxtpcUC3g';return true;" onclick=3D=
"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fopen-std.org%=
2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2015%2Fp0114r0.pdf\x26sa\x3dD\x26snt=
z\x3d1\x26usg\x3dAFQjCNHiqyTXibcdjweNAkVM9dxtpcUC3g';return true;">exac=
tly what the resumable expressions proposal used</a>. Only it was a bit cle=
verer about it, such that you would just have a resumable function called &=
quot;await" that could be overloaded for some "awaitable" ty=
pe, which would do the scheduling and unpacking, returning the unpacked val=
ue once resumed.=C2=A0</div></div></blockquote><blockquote class=3D"gmail_q=
uote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div><br>You really should look at that proposal; it=
9;s clearly what you want. And yes, it was looked at, but it didn't mov=
e forward past P0114R0.</div></div></blockquote><div><br></div><div>Thank y=
ou, I will read it. But as I said -- it isn't what I was talking about.=
</div></div></div></div></blockquote></span><div><br>How can you say it isn=
't what you were talking about when you <i>haven't read it</i>?</di=
v></div></blockquote><div><br></div><div>I meant I did not propose a new de=
sign -- I presented an idea (for current design) that may change it a bit o=
pening up some options.</div></div></div></div></blockquote><div><br>You ke=
ep saying that it's not a new design, and yet all evidence says that it=
is. Here are a number of aspects of the design of Coroutines TS:<br><br>1.=
Coroutines appear to be regular functions using a regular interface. Funct=
ion overloading works as normal with them.<br>2. Coroutines have a built-in=
and hidden state object with an internal return value object.<br>3. The in=
ternal functor that represents a coroutine is only visible to the code that=
absolutely needs to know it exists: the code which schedules its resumptio=
n.<br>4. The scheduling of the resumption of the coroutine is done entirely=
from within the coroutine itself. It may delegate this to the caller, but =
this is something it must explicitly choose to do.<br>5. There is direct an=
d <i>effortless</i> support for suspend-up via the `co_await` operator and =
its associated machinery.<br><br>I would say that most of these are <i>fund=
amental</i> aspects of what makes the Coroutines TS what it is. Here is how=
your design compares:<br><br>1. Coroutines are not regular functions. You =
haven't explained how function overloading works with coroutines.<br>2.=
Coroutines do not have built-in and hidden state objects; they directly ex=
pose this state to the code talking about them.<br>3. The code calling a co=
routine must interact with the internal functor that represents a coroutine=
..<br>4. Scheduling the resumption of the coroutine is always granted to the=
caller. <br>5. Suspend-up requires explicit effort from the caller. There =
is apparently no `co_await` operator at all.<br><br>It's not even clear=
if your system allows the user to create their own=20
promise/future types. Coroutines TS allows this by default; the=20
coroutine machinery inspects the coroutine function's signature to=20
determine what the internal promise object will be (if your return value
is std::future<T>, the promise type would be=20
std::promise<T>). Yours seems to require the caller to decide what
kind of promise/future will be used. So there's another difference.<br=
><br>How can you say that these changes do not constitute a "new desig=
n" (and, as I keep reminding you, your design is almost <i>exactly</i>=
P0114)? You're not making a minor tweak to an existing propsoal; you&#=
39;re fundamentally changing it. You even seem to understand that when you =
agreed with Todd's analogy with lambdas. An "always type-erased&qu=
ot; lambda is very much a new design compared to a "not type-erased&qu=
ot; lambda. They may do similar things, but they do them in a fundamentally=
different way.<br></div><br>To you and your use cases, this may not seem l=
ike a big change. But every use case you've presented is for suspend-do=
wn, not for suspend-up style coding. And suspend-up is what the Coroutines =
TS is all about.<br><br>So this very much is a new design.<br></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/331fb2e5-be21-4795-b73e-396fb39ccf24%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/331fb2e5-be21-4795-b73e-396fb39ccf24=
%40isocpp.org</a>.<br />
------=_Part_5654_1756084715.1520617100177--
------=_Part_5653_1841043181.1520617100176--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Fri, 9 Mar 2018 14:14:00 -0600
Raw View
--001a114b0fcee1824b0567006e55
Content-Type: text/plain; charset="UTF-8"
On Fri, Mar 9, 2018 at 11:33 AM, Lee Howes <xrikcus@gmail.com> wrote:
> On 9 March 2018 at 09:30, Lee Howes <xrikcus@gmail.com> wrote:
>
>> > coroutine void coro_bar(...) { ... }
>> > class Foo {
>> > virtual Awaitable bar() { return cb_(); }
>> > coro_bar cb_; // an instance of state-machine class generated from
>> coro_bar's definition
>> > };
>>
>> > does it make sense? I didn't think about it this way, but it should
>> probably work.
>>
>> You've added shared state. Now what happens if I want to do something
>> like this:
>>
>> Foo f;
>> thread t([&](){await f.bar());
>> thread t2([&](){await f.bar());
>> t.join();
>> t2.join();
>>
>> I need two copies of cb_, or for cb_ to use heap allocation magic to hide
>> that, or at the very least to synchronize the coroutine state.
>>
>
Ah, now I understand what you wanted to do. In this case:
coroutine void coro_bar(...) { ... }
class Foo {
virtual Awaitable bar()
{
auto cb = new coro_bar(); // basically same thing current TS does
under the hood
return (*cb)();
}
};
Ok, enter sent the message. I wanted to also add:
> > move coroutine declarions into separate TU and hide them behind plain
> function.
> but then I am back needing hooks like the coroutines TS provides - but
> unlike the coroutines TS I don't see from your example what type that plain
> function should return. So now, I wrap my coroutine in a free function foo.
> something foo();
> bar() {
> await foo()? I'm not sure what the syntax would be here for awaiting on
> a plain function... do I need a coroutine type defined here?
> }
>
corotuine void coro_foo() {...}
awaitable<void> bar()
{
auto cb = new coro_foo();
return (*cb)();
}
// somewhere in another TU
awaitable<void> bar();
co_await bar();
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4zM9ivnJ3VPq8HT1cWUkfZ%2BwfXhdK0D5K5TG1qY4CHqw%40mail.gmail.com.
--001a114b0fcee1824b0567006e55
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">=
On Fri, Mar 9, 2018 at 11:33 AM, Lee Howes <span dir=3D"ltr"><<a href=3D=
"mailto:xrikcus@gmail.com" target=3D"_blank">xrikcus@gmail.com</a>></spa=
n> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On 9 March 201=
8 at 09:30, Lee Howes <span dir=3D"ltr"><<a href=3D"mailto:xrikcus@gmail=
..com" target=3D"_blank">xrikcus@gmail.com</a>></span> wrote:<br></div><d=
iv><div class=3D"m_-1992343029764590689h5"><div class=3D"gmail_extra"><div =
class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0=
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span=
><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:1=
2.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:nor=
mal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;=
text-transform:none;white-space:normal;word-spacing:0px;background-color:rg=
b(255,255,255);text-decoration-style:initial;text-decoration-color:initial"=
>> coroutine void coro_bar(...) { ... }</div><div style=3D"color:rgb(34,=
34,34);font-family:arial,sans-serif;font-size:12.8px;font-style:normal;font=
-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-s=
pacing:normal;text-align:start;text-indent:0px;text-transform:none;white-sp=
ace:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decorati=
on-style:initial;text-decoration-color:initial"><span style=3D"font-size:12=
..8px">> class Foo {</span><br></div><div style=3D"color:rgb(34,34,34);fo=
nt-family:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-=
ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:no=
rmal;text-align:start;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:=
initial;text-decoration-color:initial"><div style=3D"color:rgb(34,34,34);fo=
nt-family:arial,sans-serif;font-style:normal;font-variant-ligatures:normal;=
font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:s=
tart;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0p=
x;text-decoration-style:initial;text-decoration-color:initial;font-size:12.=
8px;background-color:rgb(255,255,255)">>=C2=A0 =C2=A0virtual Awaitable b=
ar() { return cb_(); }</div><div style=3D"color:rgb(34,34,34);font-family:a=
rial,sans-serif;font-style:normal;font-variant-ligatures:normal;font-varian=
t-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-i=
ndent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-deco=
ration-style:initial;text-decoration-color:initial;font-size:12.8px;backgro=
und-color:rgb(255,255,255)">>=C2=A0 =C2=A0 =C2=A0coro_bar cb_;=C2=A0 // =
an instance of state-machine class generated from coro_bar's definition=
</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-s=
tyle:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-wei=
ght:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transfo=
rm:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;t=
ext-decoration-color:initial;font-size:12.8px;background-color:rgb(255,255,=
255)">> };</div><br></div><div style=3D"color:rgb(34,34,34);font-family:=
arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;te=
xt-decoration-color:initial">> does it make sense? I didn't think ab=
out it this way, but it should probably work.</div></span><span class=3D"m_=
-1992343029764590689m_1179020948615292555m_7570799115696749087gmail-im" sty=
le=3D"color:rgb(80,0,80);font-family:arial,sans-serif;font-size:12.8px;font=
-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-w=
eight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-trans=
form:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,=
255);text-decoration-style:initial;text-decoration-color:initial"><div><spa=
n class=3D"m_-1992343029764590689m_1179020948615292555m_7570799115696749087=
gmail-im" style=3D"color:rgb(80,0,80);font-family:arial,sans-serif;font-siz=
e:12.8px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:=
normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0=
px;text-transform:none;white-space:normal;word-spacing:0px;background-color=
:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initi=
al"><br></span></div>You've added shared state. Now what happens if I w=
ant to do something like this:</span><div><br></div><div>Foo f;</div><div>t=
hread t([&](){await=C2=A0 f.bar());</div><div><span style=3D"color:rgb(=
34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;fo=
nt-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decora=
tion-style:initial;text-decoration-color:initial;float:none;display:inline"=
>thread t2([&](){await=C2=A0 f.bar());</span><br></div><div>t.join();</=
div><div>t2.join();</div><div><br></div><div>I need two copies of cb_, or f=
or cb_ to use heap allocation magic to hide that, or at the very least to s=
ynchronize the coroutine state.</div></div></blockquote></div></div></div><=
/div></blockquote><div><br></div><div>Ah, now I understand what you wanted =
to do. In this case:</div><div><br></div></div></div><blockquote style=3D"m=
argin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div c=
lass=3D"gmail_quote"><div><div style=3D"font-style:normal;font-variant-liga=
tures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal=
;text-align:start;text-indent:0px;text-transform:none;white-space:normal;wo=
rd-spacing:0px;text-decoration-style:initial;text-decoration-color:initial;=
color:rgb(34,34,34);font-size:12.8px;background-color:rgb(255,255,255)"><fo=
nt face=3D"monospace, monospace">coroutine void coro_bar(...) { ... }</font=
></div></div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quo=
te"><div><div style=3D"font-style:normal;font-variant-ligatures:normal;font=
-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start=
;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;te=
xt-decoration-style:initial;text-decoration-color:initial;color:rgb(34,34,3=
4);font-size:12.8px;background-color:rgb(255,255,255)"><span style=3D"font-=
size:12.8px"><font face=3D"monospace, monospace">class Foo {</font></span><=
/div></div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote=
"><div><div style=3D"font-style:normal;font-variant-ligatures:normal;font-v=
ariant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;t=
ext-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text=
-decoration-style:initial;text-decoration-color:initial;color:rgb(34,34,34)=
;font-size:12.8px;background-color:rgb(255,255,255)"><div style=3D"color:rg=
b(34,34,34);font-style:normal;font-variant-ligatures:normal;font-variant-ca=
ps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-inden=
t:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decorati=
on-style:initial;text-decoration-color:initial;font-size:12.8px;background-=
color:rgb(255,255,255)"><font face=3D"monospace, monospace">=C2=A0 =C2=A0 v=
irtual Awaitable bar()</font></div></div></div></div></div><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote"><div><div style=3D"font-style:normal;=
font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;lett=
er-spacing:normal;text-align:start;text-indent:0px;text-transform:none;whit=
e-space:normal;word-spacing:0px;text-decoration-style:initial;text-decorati=
on-color:initial;color:rgb(34,34,34);font-size:12.8px;background-color:rgb(=
255,255,255)"><div style=3D"color:rgb(34,34,34);font-style:normal;font-vari=
ant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacin=
g:normal;text-align:start;text-indent:0px;text-transform:none;white-space:n=
ormal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:=
initial;font-size:12.8px;background-color:rgb(255,255,255)"><font face=3D"m=
onospace, monospace">=C2=A0 =C2=A0 {</font></div></div></div></div></div></=
blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px">=
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><div style=3D"fo=
nt-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font=
-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tra=
nsform:none;white-space:normal;word-spacing:0px;text-decoration-style:initi=
al;text-decoration-color:initial;color:rgb(34,34,34);font-size:12.8px;backg=
round-color:rgb(255,255,255)"><div style=3D"color:rgb(34,34,34);font-style:=
normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:4=
00;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:no=
ne;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-d=
ecoration-color:initial;font-size:12.8px;background-color:rgb(255,255,255)"=
><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 auto cb =
=3D new coro_bar(); // basically same thing current TS does under the hood<=
/font></div></div></div></div></div></blockquote><blockquote style=3D"margi=
n:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div><div style=3D"font-style:normal;font-variant-ligature=
s:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;tex=
t-align:start;text-indent:0px;text-transform:none;white-space:normal;word-s=
pacing:0px;text-decoration-style:initial;text-decoration-color:initial;colo=
r:rgb(34,34,34);font-size:12.8px;background-color:rgb(255,255,255)"><div st=
yle=3D"color:rgb(34,34,34);font-style:normal;font-variant-ligatures:normal;=
font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:s=
tart;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0p=
x;text-decoration-style:initial;text-decoration-color:initial;font-size:12.=
8px;background-color:rgb(255,255,255)"><span style=3D"font-size:12.8px"><fo=
nt face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 return (*cb)()=
;</font></span></div><div style=3D"color:rgb(34,34,34);font-style:normal;fo=
nt-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration=
-color:initial;font-size:12.8px;background-color:rgb(255,255,255)"><span st=
yle=3D"font-size:12.8px"><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =
}</font></span></div></div></div></div></div><div class=3D"gmail_extra"><di=
v class=3D"gmail_quote"><div><div style=3D"font-style:normal;font-variant-l=
igatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initi=
al;color:rgb(34,34,34);font-size:12.8px;background-color:rgb(255,255,255)">=
<div style=3D"color:rgb(34,34,34);font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;text-decoration-style:initial;text-decoration-color:initial;font-s=
ize:12.8px;background-color:rgb(255,255,255)"><span style=3D"font-family:mo=
nospace,monospace;font-size:12.8px">};</span></div></div></div></div></div>=
</blockquote><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>=C2=
=A0</div></div><div><br></div><div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left:1px solid rgb(204,204,204);padding-left:1ex">Ok, enter sent the messag=
e. I wanted to also add:<br><span style=3D"color:rgb(34,34,34);font-family:=
arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;te=
xt-decoration-color:initial;float:none;display:inline">> move coroutine =
declarions into separate TU and hide them behind plain function.</span><spa=
n style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:12.8p=
x;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;=
font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text=
-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(25=
5,255,255);text-decoration-style:initial;text-decoration-color:initial;floa=
t:none;display:inline"><br></span><span style=3D"color:rgb(34,34,34);font-f=
amily:arial,sans-serif;font-size:12.8px;font-style:normal;font-variant-liga=
tures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal=
;text-align:start;text-indent:0px;text-transform:none;white-space:normal;wo=
rd-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:init=
ial;text-decoration-color:initial;float:none;display:inline">but then I am =
back needing hooks like the coroutines TS provides - but unlike the corouti=
nes TS I don't see from your example what type that plain function shou=
ld return. So now, I wrap my coroutine in a free function foo.</span><br><s=
pan style=3D"font-size:12.8px">something foo();</span><span style=3D"font-s=
ize:12.8px"><br></span><span style=3D"font-size:12.8px">bar() {<br></span><=
span style=3D"font-size:12.8px">=C2=A0 await foo()? I'm not sure what t=
he syntax would be here for awaiting on a plain function... do I need a cor=
outine type defined here?=C2=A0<br></span><span style=3D"font-size:12.8px">=
}</span><br style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-=
size:small;font-style:normal;font-variant-ligatures:normal;font-variant-cap=
s:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent=
:0px;text-transform:none;white-space:normal;word-spacing:0px;background-col=
or:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:ini=
tial"></blockquote><div><div class=3D"gmail-m_-1992343029764590689h5"><div =
class=3D"gmail_extra"><br class=3D"gmail-Apple-interchange-newline">
</div></div></div></div></div><blockquote style=3D"margin:0 0 0 40px;border=
:none;padding:0px"><div class=3D"gmail_extra"><div><div><div class=3D"gmail=
-m_-1992343029764590689h5"><div class=3D"gmail_extra"><font face=3D"monospa=
ce, monospace">corotuine void coro_foo() {...}</font></div></div></div></di=
v></div><div class=3D"gmail_extra"><div><div class=3D"gmail-m_-199234302976=
4590689h5"><div class=3D"gmail_extra"><font face=3D"monospace, monospace"><=
br></font></div></div></div></div><div class=3D"gmail_extra"><div><div clas=
s=3D"gmail-m_-1992343029764590689h5"><div class=3D"gmail_extra"><font face=
=3D"monospace, monospace">awaitable<void> bar()</font></div></div></d=
iv></div><div class=3D"gmail_extra"><div><div class=3D"gmail-m_-19923430297=
64590689h5"><div class=3D"gmail_extra"><font face=3D"monospace, monospace">=
{</font></div></div></div></div><div class=3D"gmail_extra"><div><div class=
=3D"gmail-m_-1992343029764590689h5"><div class=3D"gmail_extra"><font face=
=3D"monospace, monospace">=C2=A0 =C2=A0 auto cb =3D new coro_foo();</font><=
/div></div></div></div><div class=3D"gmail_extra"><div><div class=3D"gmail-=
m_-1992343029764590689h5"><div class=3D"gmail_extra"><font face=3D"monospac=
e, monospace">=C2=A0 =C2=A0 return (*cb)();</font></div></div></div></div><=
div class=3D"gmail_extra"><div><div class=3D"gmail-m_-1992343029764590689h5=
"><div class=3D"gmail_extra"><font face=3D"monospace, monospace">}</font></=
div></div></div></div></blockquote><div class=3D"gmail_extra"><div><div cla=
ss=3D"gmail-m_-1992343029764590689h5"><div class=3D"gmail_extra"><br></div>=
</div></div></div><blockquote style=3D"margin:0 0 0 40px;border:none;paddin=
g:0px"><div class=3D"gmail_extra"><div><div class=3D"gmail-m_-1992343029764=
590689h5"><div class=3D"gmail_extra">// somewhere in another TU</div><div c=
lass=3D"gmail_extra">
<span style=3D"color:rgb(34,34,34);font-family:monospace,monospace;font-siz=
e:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initia=
l;float:none;display:inline">awaitable<void> bar();</span><br></div><=
div class=3D"gmail_extra"><span style=3D"color:rgb(34,34,34);font-family:mo=
nospace,monospace;font-size:small;font-style:normal;font-variant-ligatures:=
normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-=
align:start;text-indent:0px;text-transform:none;white-space:normal;word-spa=
cing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;te=
xt-decoration-color:initial;float:none;display:inline"><br></span></div></d=
iv></div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;border:n=
one;padding:0px"><div class=3D"gmail_extra"><div><div class=3D"gmail-m_-199=
2343029764590689h5"><div class=3D"gmail_extra"><span style=3D"color:rgb(34,=
34,34);font-family:monospace,monospace;font-size:small;font-style:normal;fo=
nt-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decora=
tion-style:initial;text-decoration-color:initial;float:none;display:inline"=
>co_await bar();</span></div></div></div></div></blockquote><div class=3D"g=
mail_extra"><div><br></div><div><br></div><div>Sincerely yours,<br></div><d=
iv class=3D"m_-1992343029764590689gmail_signature" data-smartmail=3D"gmail_=
signature">Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4zM9ivnJ3VPq8HT1cWUkfZ%2BwfX=
hdK0D5K5TG1qY4CHqw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP4zM9=
ivnJ3VPq8HT1cWUkfZ%2BwfXhdK0D5K5TG1qY4CHqw%40mail.gmail.com</a>.<br />
--001a114b0fcee1824b0567006e55--
.
Author: Michael Kilburn <crusader.mike@gmail.com>
Date: Fri, 9 Mar 2018 16:00:39 -0600
Raw View
--94eb2c1cd21043259a056701ec6c
Content-Type: text/plain; charset="UTF-8"
On Fri, Mar 9, 2018 at 11:38 AM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Friday, March 9, 2018 at 4:10:36 AM UTC-5, Michael Kilburn wrote:
>>
>> On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>
>>> You are not being misunderstood. You're trying to equate all "stackless
>>> coroutine" proposals; you're claiming that they're all just minor
>>> variations of the same concept.
>>>
>>
>> No, I don't. But you correctly noted that some of existing proposals
>> already have "always visible" feature. That is ok -- I presented this idea
>> in context of current proposal in order to enable options of:
>> - manually controlling generated state machine object (allocation, etc)
>> to make heap elision optimization irrelevant
>> - changing convention -- e.g. use co_nowait instead of c_await (see my
>> answer to Todd)
>> - few others
>>
>> If you don't like any of these options -- naturally, that idea is a no
>> go. But maybe some of them can be appealing?
>>
>
> It's not a question of liking or disliking the options. These options are
> irrelevant for the use cases that the Coroutines TS is intended to work
> with. They force the system to move away from the optimal syntax for
> suspend-up-style programming and towards a suspend-down model.
>
> The basic concepts you're describing are appealing; I implore you to read
> P0114. But they are not appropriate *for this proposal*. Your idea is
> trying to turn a suspend-up system into a suspend-down one.
>
No, the idea is to force all coroutines to be inline and clearly mark them
as coroutines. At minimum, everything else can stay the same -- return
types, semantics, co_* keywords, etc.
> *They are not*. Coroutines TS is not just creating a resumable function;
>>> it's a lot more than that. It's implementing a specific model of
>>> coroutines, which is different from the model you're defining.
>>>
>>> If you want "just resumable functions", then you need to understand that
>>> this really is a completely different proposal with a completely different
>>> design from the Coroutines TS. It's not a slight modification of Coroutines
>>> TS (which is evidence in the fact that your design literally removes all of
>>> the Coroutines TS's keywords).
>>>
>>
>> keywords maybe removed but their intended effect stays unchanged.
>>
>
> How can something which no longer exist have an effect?
>
like this:
coroutine ... coro1() { ... }
coroutine ... coro2() {
coro1(); // we know coro1 is a coroutine
(because coro1 is marked so) and we know it is being invoked from a
coroutine(because coro2 is marked so)
// therefore we may choose to await by
default when calling it
auto x = co_noawait coro1(); // ... and (for example) require a
keyword for non-awaiting call (to distinguish between two calling modes)
}
again -- it is just an option, it allows us to use co_await on coroutine
calls (while retaining co_await semantics). You may argue that having
explicit co_await is better for aesthetic (or some other) purpose -- I am
fine with that.
For example, how does one of your coroutines yield values? What's funny is
> that, since I've read P0114, I have a pretty good idea what your answer
> will be ;)
>
same as it is done today -- co_yield
Why it wouldn't work? coro_foo() will end up calling async_foo() passing my
>> current coroutine resume() as a callback and suspending (i.e. returning).
>> Code will be practically the same. I either fantastically missing something
>> or we are not on the same page.
>>
>
> Show me how the code would "be practically the same". Present the
> equivalent code using your idea.
>
> And please note that it must be the *equivalent code*: based on `.then`
> style continuations and the like. So the return value still needs to be a
> `task<string>`. And the function itself must be a regular function (and
> thus cannot directly use your `coroutine` keyword).
>
My idea has nothing to do with all this -- here we were exploring
differences between library that uses callback-based API (it will have
async_foo() and coro_foo() for each "foo") and library that uses
futures/tasks (which will have only one foo()). My note was that I don't
see particular advantage of second approach. I didn't set the goal of
reproducing .then-style continuations, in fact question was "why would you
use futures approach if other one is more efficient and can produce very
similar client code?". Nevertheless, here is the blueprint of how it may
look like:
void async_foo(..., user_cb, user_cb_data);
inline string coro_foo(...) // as mentioned before coro_foo has to be
inline or macro (to be able to have access to coroutine that calls it)
{
string ret;
struct control_struct {
...
} control(&ret, ¤t_coro.resume);
auto cb = [](..., user_cb_data) {
((control_struct*)user_cb_data)->set_result_and_call_resume(
make_string(...) );
};
async_foo(..., cb, &control);
suspend_current_coro;
return ret;
}
// user code:
coroutine string coro_user1(...)
{
string chunk = coro_foo(...);
while((chunk = coro_foo(...)).size()) ...;
...
}
i.e. it can be done without heap allocations, etc and you still end up with
the same simple user-side code. This probably can be optimized further --
coroutine can have multiple resume() methods with different signature (so
that data foo passed into callback could be passed directly into coroutine
as part of resumption (removing need for "string ret")). Or maybe some
trick to avoid calling "string ret" ctor -- that lambda can construct "ret"
in-place.
but I'll repeat again -- this detraction has nothing to do with my
idea!!!!! It was an attempt to figure out how library API (and coroutines)
may look like without using futures/etc.
The kind of design you've presented is exactly what the resumable
>>>>> expressions proposal used
>>>>> <http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf>.
>>>>> Only it was a bit cleverer about it, such that you would just have a
>>>>> resumable function called "await" that could be overloaded for some
>>>>> "awaitable" type, which would do the scheduling and unpacking, returning
>>>>> the unpacked value once resumed.
>>>>>
>>>>
>>>>> You really should look at that proposal; it's clearly what you want.
>>>>> And yes, it was looked at, but it didn't move forward past P0114R0.
>>>>>
>>>>
>>>> Thank you, I will read it. But as I said -- it isn't what I was talking
>>>> about.
>>>>
>>>
>>> How can you say it isn't what you were talking about when you *haven't
>>> read it*?
>>>
>>
>> I meant I did not propose a new design -- I presented an idea (for
>> current design) that may change it a bit opening up some options.
>>
>
> You keep saying that it's not a new design, and yet all evidence says that
> it is. Here are a number of aspects of the design of Coroutines TS:
>
> 1. Coroutines appear to be regular functions using a regular interface.
> Function overloading works as normal with them.
> 2. Coroutines have a built-in and hidden state object with an internal
> return value object.
> 3. The internal functor that represents a coroutine is only visible to the
> code that absolutely needs to know it exists: the code which schedules its
> resumption.
> 4. The scheduling of the resumption of the coroutine is done entirely from
> within the coroutine itself. It may delegate this to the caller, but this
> is something it must explicitly choose to do.
> 5. There is direct and *effortless* support for suspend-up via the
> `co_await` operator and its associated machinery.
>
> I would say that most of these are *fundamental* aspects of what makes
> the Coroutines TS what it is. Here is how your design compares:
>
> 1. Coroutines are not regular functions. You haven't explained how
> function overloading works with coroutines.
> 2. Coroutines do not have built-in and hidden state objects; they directly
> expose this state to the code talking about them.
> 3. The code calling a coroutine must interact with the internal functor
> that represents a coroutine.
> 4. Scheduling the resumption of the coroutine is always granted to the
> caller.
> 5. Suspend-up requires explicit effort from the caller. There is
> apparently no `co_await` operator at all.
>
> It's not even clear if your system allows the user to create their own
> promise/future types. Coroutines TS allows this by default; the coroutine
> machinery inspects the coroutine function's signature to determine what the
> internal promise object will be (if your return value is std::future<T>,
> the promise type would be std::promise<T>). Yours seems to require the
> caller to decide what kind of promise/future will be used. So there's
> another difference.
>
> How can you say that these changes do not constitute a "new design" (and,
> as I keep reminding you, your design is almost *exactly* P0114)? You're
> not making a minor tweak to an existing propsoal; you're fundamentally
> changing it. You even seem to understand that when you agreed with Todd's
> analogy with lambdas. An "always type-erased" lambda is very much a new
> design compared to a "not type-erased" lambda. They may do similar things,
> but they do them in a fundamentally different way.
>
> To you and your use cases, this may not seem like a big change. But every
> use case you've presented is for suspend-down, not for suspend-up style
> coding. And suspend-up is what the Coroutines TS is all about.
>
> So this very much is a new design.
>
Here I can only bang my head against the desk -- you've decided for
yourself what I am trying to present and no amount of arguing can cause you
to budge. I can only give up :-)
--
Sincerely yours,
Michael.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7en69xgUrDp6J1rMwAThTKWS_CJx6X9M9yyK0gNrU0wQ%40mail.gmail.com.
--94eb2c1cd21043259a056701ec6c
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On F=
ri, Mar 9, 2018 at 11:38 AM, Nicol Bolas <span dir=3D"ltr"><<a href=3D"m=
ailto:jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></s=
pan> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Friday, M=
arch 9, 2018 at 4:10:36 AM UTC-5, Michael Kilburn wrote:<span class=3D""><b=
lockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote">On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <span dir=3D"ltr">=
<<a rel=3D"nofollow">jmck...@gmail.com</a>></span> wrote:<br><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>You are not being misunderstoo=
d. You're trying to equate all "stackless=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br></div></div></blockquote><div><br></=
div><div>No, I don't. But you correctly noted that some of existing pro=
posals already have "always visible" feature. That is ok -- I pre=
sented this idea in context of current proposal in order to enable options =
of:</div><div>- manually controlling generated state machine object (alloca=
tion, etc) to make heap elision optimization irrelevant</div><div>- changin=
g convention -- e.g. use co_nowait instead of c_await (see my answer to Tod=
d)</div><div>- few others</div><div><br></div><div>If you don't like an=
y of these options -- naturally, that idea is a no go. But maybe some of th=
em can be appealing?</div></div></div></div></blockquote></span><div><br>It=
's not a question of liking or disliking the options. These options are=
irrelevant for the use cases that the Coroutines TS is intended to work wi=
th. They force the system to move away from the optimal syntax for suspend-=
up-style programming and towards a suspend-down model.<br><br>The basic con=
cepts you're describing are appealing; I implore you to read P0114. But=
they are not appropriate <i>for this proposal</i>. Your idea is trying to =
turn a suspend-up system into a suspend-down one.<br></div></div></blockquo=
te><div><br></div><div>No, the idea is to force all coroutines to be inline=
and clearly mark them as coroutines. At minimum, everything else can stay =
the same -- return types, semantics, co_* keywords, etc.</div><div><br></di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
..8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span cl=
ass=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div=
class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div=
><i>They are not</i>. Coroutines TS is not just creating a resumable functi=
on; it's a lot more than that. It's implementing a specific model o=
f coroutines, which is different from the model you're defining.<br><br=
>If you want "just resumable functions", then you need to underst=
and that this really is a completely different proposal with a completely d=
ifferent design from the Coroutines TS. It's not a slight modification =
of Coroutines TS (which is evidence in the fact that your design literally =
removes all of the Coroutines TS's keywords).<br></div></div></blockquo=
te><div><br></div><div>keywords maybe removed but their intended effect sta=
ys unchanged.</div></div></div></div></blockquote></span><div><br>How can s=
omething which no longer exist have an effect?<br></div></div></blockquote>=
<div><br></div><div>like this:</div></div></div><blockquote style=3D"margin=
:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div><font face=3D"monospace, monospace">coroutine ... cor=
o1() { ... }</font></div></div></div><div class=3D"gmail_extra"><div class=
=3D"gmail_quote"><div><font face=3D"monospace, monospace"><br></font></div>=
</div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><fon=
t face=3D"monospace, monospace">coroutine ... coro2() {</font></div></div><=
/div></blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;paddin=
g:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font fac=
e=3D"monospace, monospace">=C2=A0 =C2=A0 coro1();=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // we know coro=
1 is a coroutine (because coro1 is marked so) and we know it is being invok=
ed from a coroutine(because coro2 is marked so)</font></div><div><font face=
=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 // therefore we may choose to await by default when calling it</font></=
div></div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;border:=
none;padding:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><di=
v><font face=3D"monospace, monospace">=C2=A0 =C2=A0 auto x =3D co_noawait c=
oro1();=C2=A0 =C2=A0 // ... and (for example) require a keyword for non-awa=
iting call (to distinguish between two calling modes)</font></div></div></d=
iv></blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;padding:=
0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=
=3D"monospace, monospace">}</font></div><div><font face=3D"monospace, monos=
pace"><br></font></div></div></div></blockquote><div>again -- it is just an=
option, it allows us to use co_await on coroutine calls (while retaining c=
o_await semantics). You may argue that having explicit co_await is better f=
or aesthetic (or some other) purpose -- I am fine with that.</div><br><div =
class=3D"gmail_extra"><div class=3D"gmail_quote"><div><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><div>For example, how does one of your=
coroutines yield values? What's funny is that, since I've read P01=
14, I have a pretty good idea what your answer will be ;)<br></div></div></=
blockquote><div><br></div><div>same as it is done today -- co_yield</div><d=
iv><br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1e=
x"><div dir=3D"ltr"><span class=3D""><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);paddin=
g-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div dir=3D"lt=
r"><div>Why it wouldn't work? coro_foo() will end up calling async_foo(=
) passing my current coroutine resume() as a callback and suspending (i.e. =
returning). Code will be practically the same. I either fantastically missi=
ng something or we are not on the same page.<br></div></div></div></div></d=
iv></blockquote></span><div><br>Show me how the code would "be practic=
ally the same". Present the equivalent code using your idea.<br><br>An=
d please note that it must be the <i>equivalent code</i>: based on `.then` =
style continuations and the like. So the return value still needs to be a `=
task<string>`. And the function itself must be a regular function (an=
d thus cannot directly use your `coroutine` keyword).<br></div></div></bloc=
kquote><div><br></div><div>My idea has nothing to do with all this -- here =
we were exploring differences between library that uses callback-based API =
(it will have async_foo() and coro_foo() for each "foo") and libr=
ary that uses futures/tasks (which will have only one foo()). My note was t=
hat I don't see particular advantage of second approach. I didn't s=
et the goal of reproducing .then-style continuations, in fact question was =
"why would you use futures approach if other one is more efficient and=
can produce very similar client code?". Nevertheless, here is the blu=
eprint of how it may look like:</div><div><br></div></div></div><blockquote=
style=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_ex=
tra"><div class=3D"gmail_quote"><div><font face=3D"monospace, monospace">vo=
id async_foo(..., user_cb, user_cb_data);</font></div></div></div><div clas=
s=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"monospace, =
monospace"><br></font></div></div></div><div class=3D"gmail_extra"><div cla=
ss=3D"gmail_quote"><div><font face=3D"monospace, monospace">inline string c=
oro_foo(...)=C2=A0 =C2=A0 =C2=A0// as mentioned before coro_foo has to be i=
nline or macro (to be able to have access to coroutine that calls it)</font=
></div></div></div><div class=3D"gmail_extra"><div class=3D"gmail_quote"><d=
iv><font face=3D"monospace, monospace">{</font></div></div></div></blockquo=
te><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div cla=
ss=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"monospace,=
monospace">=C2=A0 =C2=A0 string ret;</font></div></div></div></blockquote>=
<blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=
=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"monospace, m=
onospace">=C2=A0 =C2=A0 struct control_struct {</font></div><div><font face=
=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 ...</font></div></div=
></div></blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;padd=
ing:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><font f=
ace=3D"monospace, monospace">=C2=A0 =C2=A0 } control(&ret, &current=
_coro.resume);</font></div></div></div></blockquote><blockquote style=3D"ma=
rgin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0=
=C2=A0</font></div></div></div></blockquote><blockquote style=3D"margin:0 0=
0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div class=3D"g=
mail_quote"><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 auto cb =
=3D=C2=A0<span style=3D"color:rgb(34,34,34);font-family:monospace,monospace=
;font-size:small;font-style:normal;font-variant-ligatures:normal;font-varia=
nt-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgrou=
nd-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-col=
or:initial;float:none;display:inline">[](..., user_cb_data) {</span></font>=
</div><div><font face=3D"monospace, monospace"><span style=3D"color:rgb(34,=
34,34);font-family:monospace,monospace;font-size:small;font-style:normal;fo=
nt-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decora=
tion-style:initial;text-decoration-color:initial;float:none;display:inline"=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((<span style=3D"color:rgb(34,34,34);font-fami=
ly:monospace,monospace;font-size:small;font-style:normal;font-variant-ligat=
ures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;=
text-align:start;text-indent:0px;text-transform:none;white-space:normal;wor=
d-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initi=
al;text-decoration-color:initial;float:none;display:inline">control_struct<=
/span>*)user_cb_data)->set_result_and_call_resume( make_string(...) );</=
span></font></div><div><font face=3D"monospace, monospace"><span style=3D"c=
olor:rgb(34,34,34);font-family:monospace,monospace;font-size:small;font-sty=
le:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weigh=
t:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform=
:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)=
;text-decoration-style:initial;text-decoration-color:initial;float:none;dis=
play:inline">=C2=A0 =C2=A0 };=C2=A0</span></font></div></div></div></blockq=
uote><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div c=
lass=3D"gmail_extra"><div class=3D"gmail_quote"><div><font face=3D"monospac=
e, monospace">=C2=A0 =C2=A0 async_foo(..., cb, &<span style=3D"color:rg=
b(34,34,34);font-family:monospace,monospace;font-size:small;font-style:norm=
al;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;l=
etter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;w=
hite-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-d=
ecoration-style:initial;text-decoration-color:initial;float:none;display:in=
line">control</span>);</font></div></div></div></blockquote><blockquote sty=
le=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"=
><div class=3D"gmail_quote"><div><font face=3D"monospace, monospace">=C2=A0=
=C2=A0 suspend_current_coro;</font></div></div></div></blockquote><blockqu=
ote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail=
_extra"><div class=3D"gmail_quote"><div><font face=3D"monospace, monospace"=
>=C2=A0 =C2=A0 return ret;</font></div></div></div></blockquote><blockquote=
style=3D"margin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_ex=
tra"><div class=3D"gmail_quote"><div><font face=3D"monospace, monospace">}<=
/font></div><div><br></div></div></div></blockquote><blockquote style=3D"ma=
rgin:0 0 0 40px;border:none;padding:0px"><div class=3D"gmail_extra"><div cl=
ass=3D"gmail_quote"><div><font face=3D"monospace, monospace">// user code:<=
/font></div></div></div></blockquote><blockquote style=3D"margin:0 0 0 40px=
;border:none;padding:0px"><font face=3D"monospace, monospace">coroutine str=
ing coro_user1(...)<br>{<br>=C2=A0 string chunk =3D=20
<span style=3D"color:rgb(34,34,34);font-family:monospace,monospace;font-siz=
e:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initia=
l;float:none;display:inline">coro_foo(...)</span>;<br>=C2=A0 while((chunk =
=3D=20
<span style=3D"color:rgb(34,34,34);font-family:monospace,monospace;font-siz=
e:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initia=
l;float:none;display:inline">coro_foo(...)</span>).size()) ...;<br>=C2=A0 .=
...<br>}<br></font></blockquote><div><br></div><div>i.e. it can be done with=
out heap allocations, etc and you still end up with the same simple user-si=
de code. This probably can be optimized further -- coroutine can have multi=
ple resume() methods with different signature (so that data foo passed into=
callback could be passed directly into coroutine as part of resumption (re=
moving need for "string ret")). Or maybe some trick to avoid call=
ing "string ret" ctor -- that lambda can construct "ret"=
; in-place.</div><div><br></div><div>but I'll repeat again -- this detr=
action has nothing to do with my idea!!!!! It was an attempt to figure out =
how library API (and coroutines) may look like without using futures/etc.</=
div><br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><span =
class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:=
0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><d=
iv class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><s=
pan><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The =
kind of design you've presented is <a href=3D"http://open-std.org/JTC1/=
SC22/WG21/docs/papers/2015/p0114r0.pdf" rel=3D"nofollow" target=3D"_blank">=
exactly what the resumable expressions proposal used</a>. Only it was a bit=
cleverer about it, such that you would just have a resumable function call=
ed "await" that could be overloaded for some "awaitable"=
; type, which would do the scheduling and unpacking, returning the unpacked=
value once resumed.=C2=A0</div></div></blockquote><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div dir=3D"ltr"><div><br>You really should look at that proposal; i=
t's clearly what you want. And yes, it was looked at, but it didn't=
move forward past P0114R0.</div></div></blockquote><div><br></div><div>Tha=
nk you, I will read it. But as I said -- it isn't what I was talking ab=
out.</div></div></div></div></blockquote></span><div><br>How can you say it=
isn't what you were talking about when you <i>haven't read it</i>?=
</div></div></blockquote><div><br></div><div>I meant I did not propose a ne=
w design -- I presented an idea (for current design) that may change it a b=
it opening up some options.</div></div></div></div></blockquote></span><div=
><br>You keep saying that it's not a new design, and yet all evidence s=
ays that it is. Here are a number of aspects of the design of Coroutines TS=
:<br><br>1. Coroutines appear to be regular functions using a regular inter=
face. Function overloading works as normal with them.<br>2. Coroutines have=
a built-in and hidden state object with an internal return value object.<b=
r>3. The internal functor that represents a coroutine is only visible to th=
e code that absolutely needs to know it exists: the code which schedules it=
s resumption.<br>4. The scheduling of the resumption of the coroutine is do=
ne entirely from within the coroutine itself. It may delegate this to the c=
aller, but this is something it must explicitly choose to do.<br>5. There i=
s direct and <i>effortless</i> support for suspend-up via the `co_await` op=
erator and its associated machinery.<br><br>I would say that most of these =
are <i>fundamental</i> aspects of what makes the Coroutines TS what it is. =
Here is how your design compares:<br><br>1. Coroutines are not regular func=
tions. You haven't explained how function overloading works with corout=
ines.<br>2. Coroutines do not have built-in and hidden state objects; they =
directly expose this state to the code talking about them.<br>3. The code c=
alling a coroutine must interact with the internal functor that represents =
a coroutine.<br>4. Scheduling the resumption of the coroutine is always gra=
nted to the caller. <br>5. Suspend-up requires explicit effort from the cal=
ler. There is apparently no `co_await` operator at all.<br><br>It's not=
even clear if your system allows the user to create their own=20
promise/future types. Coroutines TS allows this by default; the=20
coroutine machinery inspects the coroutine function's signature to=20
determine what the internal promise object will be (if your return value
is std::future<T>, the promise type would be=20
std::promise<T>). Yours seems to require the caller to decide what
kind of promise/future will be used. So there's another difference.<br=
><br>How can you say that these changes do not constitute a "new desig=
n" (and, as I keep reminding you, your design is almost <i>exactly</i>=
P0114)? You're not making a minor tweak to an existing propsoal; you&#=
39;re fundamentally changing it. You even seem to understand that when you =
agreed with Todd's analogy with lambdas. An "always type-erased&qu=
ot; lambda is very much a new design compared to a "not type-erased&qu=
ot; lambda. They may do similar things, but they do them in a fundamentally=
different way.<br></div><br>To you and your use cases, this may not seem l=
ike a big change. But every use case you've presented is for suspend-do=
wn, not for suspend-up style coding. And suspend-up is what the Coroutines =
TS is all about.<br><br>So this very much is a new design.<br></div></block=
quote><div><br></div><div>Here I can only bang my head against the desk -- =
you've decided for yourself what I am trying to present and no amount o=
f arguing can cause you to budge. I can only give up :-)</div><div><br></di=
v></div>-- <br><div class=3D"gmail_signature" data-smartmail=3D"gmail_signa=
ture">Sincerely yours,<br>Michael.</div>
</div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7en69xgUrDp6J1rMwAThTKWS_CJx=
6X9M9yyK0gNrU0wQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CA%2BnLVP7en69x=
gUrDp6J1rMwAThTKWS_CJx6X9M9yyK0gNrU0wQ%40mail.gmail.com</a>.<br />
--94eb2c1cd21043259a056701ec6c--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 9 Mar 2018 15:14:28 -0800 (PST)
Raw View
------=_Part_6621_348091832.1520637268807
Content-Type: multipart/alternative;
boundary="----=_Part_6622_797572630.1520637268808"
------=_Part_6622_797572630.1520637268808
Content-Type: text/plain; charset="UTF-8"
On Friday, March 9, 2018 at 5:00:43 PM UTC-5, Michael Kilburn wrote:
>
> On Fri, Mar 9, 2018 at 11:38 AM, Nicol Bolas <jmck...@gmail.com
> <javascript:>> wrote:
>
>> On Friday, March 9, 2018 at 4:10:36 AM UTC-5, Michael Kilburn wrote:
>>>
>>> On Thu, Mar 8, 2018 at 11:12 AM, Nicol Bolas <jmck...@gmail.com> wrote:
>>>
>>>> You are not being misunderstood. You're trying to equate all "stackless
>>>> coroutine" proposals; you're claiming that they're all just minor
>>>> variations of the same concept.
>>>>
>>>
>>> No, I don't. But you correctly noted that some of existing proposals
>>> already have "always visible" feature. That is ok -- I presented this idea
>>> in context of current proposal in order to enable options of:
>>> - manually controlling generated state machine object (allocation, etc)
>>> to make heap elision optimization irrelevant
>>> - changing convention -- e.g. use co_nowait instead of c_await (see my
>>> answer to Todd)
>>> - few others
>>>
>>> If you don't like any of these options -- naturally, that idea is a no
>>> go. But maybe some of them can be appealing?
>>>
>>
>> It's not a question of liking or disliking the options. These options are
>> irrelevant for the use cases that the Coroutines TS is intended to work
>> with. They force the system to move away from the optimal syntax for
>> suspend-up-style programming and towards a suspend-down model.
>>
>> The basic concepts you're describing are appealing; I implore you to read
>> P0114. But they are not appropriate *for this proposal*. Your idea is
>> trying to turn a suspend-up system into a suspend-down one.
>>
>
> No, the idea is to force all coroutines to be inline and clearly mark them
> as coroutines. At minimum, everything else can stay the same -- return
> types, semantics, co_* keywords, etc.
>
It should be noted that the original coroutines design did indeed require a
keyword on the coroutine function declaration/definition: `async`. This was
dropped due to lack of need, since the outside world doesn't interact with
coroutines in a different way from regular functions.
If "everything else can stay the same" about the Coroutines TS, then you
can get the exact same effect of what you want by doing this:
[[coroutine]] inline future<int> some_coroutine(...) {...}
That is, if you want to encourage the compiler to generate nicer code by
adding some syntax and declaring the function inline, then you are free to
do so.
But this gains you nothing. After all, if "everything else can stay the
same", then the coroutine handle is still type-erased. The stack still has
to be declared as heap allocated, since there is no guarantee that the code
being given the coroutine handle will be inline as well or otherwise
visible (remember: the Coroutines TS's "semantics" are suspend-up; the
caller does not necessarily get the handle). You still have to `co_await`
or `co_yield` throughout your call stack to get to the eventual
non-coroutine caller. And so forth.
So if this "at a minimum" suggestion is what you really want, then
literally every problem you raise with the Coroutines TS remains
unresolved. What's the point? It doesn't fix anything you believe is wrong.
Clearly, if you want to solve those problems, declaring these functions
`inline` and slapping a keyword on them *alone* isn't going to get it done.
You have to actually change the *semantics* of the Coroutines TS.
Which is exactly what you've suggested, even in your original post. So
again, it's not clear why you're talking about some "at a minimum" that
doesn't match what you've actually asked for.
For example, how does one of your coroutines yield values? What's funny is
>> that, since I've read P0114, I have a pretty good idea what your answer
>> will be ;)
>>
>
> same as it is done today -- co_yield
>
The behavior of the `co_yield` expression is based on the concept of a
promise object, defined by the Coroutines TS. The type of the promise
object of a coroutine is based on the signature of the coroutine function,
using a customization point. This typically only bothers to look at the
return type, but it could look at the full signature.
`std::future<int>`, when used as a coroutine return value, would have
`std::promise<int>` be the promise object type. For some hypothetical
`generator<int>` return type, you would need to provide a
`promise_generator<int>` type to match. The current Coroutines TS proposal
doesn't have one in the standard library, but if you're going to make a
generator coroutine, that's how it would work.
But your `coroutine`-labeled functions no longer return types like
`future<int>` or `generator<int>`. This is evident by *every example you've
given here*, including the very first one:
coroutine int mycoro(int a, char* b) { ... } // has to be defined in
declaration
That function returns an `int`.
And since you have said nothing about the nature of the coroutine promise
object in your design, I must assume that your `coroutine`-qualified
functions have no such concept. And if your design still has the promise
object, then you need to explain how `mycoro` maps from returning `int` to
`promise<int>` or `promise_generator<int>` would work, since literally
*everything* in the Coroutines TS is based on the promise object type.
Because `co_yield`'s behavior is based on promise objects, it is no longer
clear what `co_yield` does in your design. So I contest the idea that it is
the "same as it is done today". Even if you keep the keyword, the actual
*behavior* of `co_yield` under your design has radically changed.
In the current design, `co_yield` stores a value in the promise object by
calling a specific function, then halts execution of the function through
the promise object, putting the coroutine_handle to be resumed in the
return value object which the caller then gets.
Since your design apparently rips out all of stuff that `co_yield` is based
on, I don't know what `co_yield` does in your design. And while what you
want it to do might conceptually have similar effects, it will achieve
these effects via completely different mechanisms. As such, this keyword
will not be the "same as it is done today".
Here I can only bang my head against the desk -- you've decided for
> yourself what I am trying to present and no amount of arguing can cause you
> to budge. I can only give up :-)
>
Maybe because what you are trying to present changes with every post you
make. Sometimes you say that we don't need `co_await` and instead use
`co_noawait` or some such. Sometimes you say that we'd still have
`co_await`. Sometimes you say that you just want inlining with no changes
to anything else. Sometimes you say that a coroutine function is an object
with some special properties that you never fully define.
It's impossible to talk concretely about a nebulous, moving target. All I
can do is look at the code you present and try to deduce from it what
you're trying to do.
For example, let's look at this piece of code:
corotuine void coro_foo() {...}
awaitable<void> bar()
{
auto cb = new coro_foo();
return (*cb)();
}
I can only hypothesize as to what this code is actually doing. You're
invoking the `new` operator on what appears to be a value of type `void`.
But since you've talked about coroutines exposing some kind of object to
the user, I assume that using `()` on an identifier that is a coroutine
function yields some kind of object. Or perhaps `coro_foo` is grammatically
a typename (in which case, coroutines cannot be overloaded). Either one
would work.
So there's this object that got heap allocated. And then you dereference
the pointer to it, and invoke its `operator()` overload, returning the
result of it. What does that do?
Again, I can only guess. There's a heap object that represents a coroutine
that has not yet started execution. You invoke `operator()` on it, and
return the result of that, constructing a thing called `awaitable<void>`.
So I'm guessing this expression kicks off the coroutine. But does it
actually invoke the coroutine function at that point?
What does the operator() return? Is it in some way related to `(*cb)`? And
if not, how does `cb` get deleted?
None of that is well-defined.
So here's an idea: write out an *actual proposal*. Not vague ideas, but a
fully-fleshed out design. And I mean something that is a fully defined as
the current Coroutines TS. I should be able to read your proposal, look at
any code that uses it, and know exactly what every expression is and how it
will behave. And right now, I cannot say that about anything you've
suggested.
I want to stop playing 20 questions with you about what you want. Lay out
the entire scheme.
And no; simply saying "be inline and clearly mark them as coroutines" is
not that. The above code is *very far* from that.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/20b6d180-e4dc-4601-8afa-af0ece50a312%40isocpp.org.
------=_Part_6622_797572630.1520637268808
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, March 9, 2018 at 5:00:43 PM UTC-5, Michael Kilb=
urn wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v><div class=3D"gmail_quote">On Fri, Mar 9, 2018 at 11:38 AM, Nicol Bolas <=
span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscat=
ed-mailto=3D"EZkteju2BAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
;javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;;return true;">jmck...@gmail.com</a>></span> wrote:<br><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr">On Friday, March 9, 2018 at 4:10:36 AM UTC-=
5, Michael Kilburn wrote:<span><blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr"><div><div class=3D"gmail_quote">On Thu, Mar 8, 2018 at 11:12 A=
M, Nicol Bolas <span dir=3D"ltr"><<a rel=3D"nofollow">jmck...@gmail.com<=
/a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><d=
iv>You are not being misunderstood. You're trying to equate all "s=
tackless=20
coroutine" proposals; you're claiming that they're all just mi=
nor variations of the same concept.<br></div></div></blockquote><div><br></=
div><div>No, I don't. But you correctly noted that some of existing pro=
posals already have "always visible" feature. That is ok -- I pre=
sented this idea in context of current proposal in order to enable options =
of:</div><div>- manually controlling generated state machine object (alloca=
tion, etc) to make heap elision optimization irrelevant</div><div>- changin=
g convention -- e.g. use co_nowait instead of c_await (see my answer to Tod=
d)</div><div>- few others</div><div><br></div><div>If you don't like an=
y of these options -- naturally, that idea is a no go. But maybe some of th=
em can be appealing?</div></div></div></div></blockquote></span><div><br>It=
's not a question of liking or disliking the options. These options are=
irrelevant for the use cases that the Coroutines TS is intended to work wi=
th. They force the system to move away from the optimal syntax for suspend-=
up-style programming and towards a suspend-down model.<br><br>The basic con=
cepts you're describing are appealing; I implore you to read P0114. But=
they are not appropriate <i>for this proposal</i>. Your idea is trying to =
turn a suspend-up system into a suspend-down one.<br></div></div></blockquo=
te><div><br></div><div>No, the idea is to force all coroutines to be inline=
and clearly mark them as coroutines. At minimum, everything else can stay =
the same -- return types, semantics, co_* keywords, etc.</div></div></div><=
/div></blockquote><div><br>It should be noted that the original coroutines =
design did indeed=20
require a keyword on the coroutine function declaration/definition: `async`=
.. This=20
was dropped due to lack of need, since the outside world doesn't=20
interact with coroutines in a different way from regular functions.<br><br>=
If "everything else can stay the same" about the Coroutines TS, t=
hen you can get the exact same effect of what you want by doing this:<br><b=
r><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187=
, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: break-w=
ord;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpr=
ettyprint"><span style=3D"color: #660;" class=3D"styled-by-prettify">[[</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">coroutine</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">]]</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">inline</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> future</span><span style=3D"color: =
#080;" class=3D"styled-by-prettify"><int></span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> some_coroutine</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(...)</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{...}</span></div></code></div><br>That is, if =
you want to encourage the compiler to generate nicer code by adding some sy=
ntax and declaring the function inline, then you are free to do so.<br><br>=
But this gains you nothing. After all, if "everything else can stay th=
e same", then the coroutine handle is still type-erased. The stack sti=
ll has to be declared as heap allocated, since there is no guarantee that t=
he code being given the coroutine handle will be inline as well or otherwis=
e visible (remember: the Coroutines TS's "semantics" are susp=
end-up; the caller does not necessarily get the handle). You still have to =
`co_await` or `co_yield` throughout your call stack to get to the eventual =
non-coroutine caller. And so forth.<br><br>So if this "at a minimum&qu=
ot; suggestion is what you really want, then literally every problem you ra=
ise with the Coroutines TS remains unresolved. What's the point? It doe=
sn't fix anything you believe is wrong.<br><br>Clearly, if you want to =
solve those problems, declaring these functions `inline` and slapping a key=
word on them <i>alone</i> isn't going to get it done. You have to actua=
lly change the <i>semantics</i> of the Coroutines TS.<br><br>Which is exact=
ly what you've suggested, even in your original post. So again, it'=
s not clear why you're talking about some "at a minimum" that=
doesn't match what you've actually asked for.<br><br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div=
>For example, how does one of your coroutines yield values? What's funn=
y is that, since I've read P0114, I have a pretty good idea what your a=
nswer will be ;)<br></div></div></blockquote><div><br></div><div>same as it=
is done today -- co_yield</div></div></div></div></blockquote><div><br>The=
behavior of the `co_yield` expression is based on the concept of a promise=
object, defined by the Coroutines TS. The type of the promise object of a =
coroutine is based on the signature of the coroutine function, using a cust=
omization point. This typically only bothers to look at the return type, bu=
t it could look at the full signature.<br><br>`std::future<int>`, whe=
n used as a coroutine return value, would have `std::promise<int>` be=
the promise object type. For some hypothetical `generator<int>` retu=
rn type, you would need to provide a `promise_generator<int>` type to=
match. The current Coroutines TS proposal doesn't have one in the stan=
dard library, but if you're going to make a generator coroutine, that&#=
39;s how it would work.<br><br>But your `coroutine`-labeled functions no lo=
nger return types like `future<int>` or `generator<int>`. This =
is evident by <i>every example you've given here</i>, including the ver=
y first one:<br><br><div style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; over=
flow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">coroutine </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> mycoro</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> a</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> =C2=A0</span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// has to be defined in declaration</span></div></c=
ode></div><br>That function returns an `int`.<br><br>And since you have sai=
d nothing about the nature of the coroutine promise object in your design, =
I must assume that your `coroutine`-qualified functions have no such concep=
t. And if your design still has the promise object, then you need to explai=
n how `mycoro` maps from returning `int` to `promise<int>` or `promis=
e_generator<int>` would work, since literally <i>everything</i> in th=
e Coroutines TS is based on the promise object type.<br><br>Because `co_yie=
ld`'s behavior is based on promise objects, it is no longer clear what =
`co_yield` does in your design. So I contest the idea that it is the "=
same as it is done today". Even if you keep the keyword, the actual <i=
>behavior</i> of `co_yield` under your design has radically changed.<br><br=
>In the current design, `co_yield` stores a value in the promise object by =
calling a specific function, then halts execution of the function through t=
he promise object, putting the coroutine_handle to be resumed in the return=
value object which the caller then gets.<br><br>Since your design apparent=
ly rips out all of stuff that `co_yield` is based on, I don't know what=
`co_yield` does in your design. And while what you want it to do might con=
ceptually have similar effects, it will achieve these effects via completel=
y different mechanisms. As such, this keyword will not be the "same as=
it is done today".<br></div><br><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div></div><div>He=
re I can only bang my head against the desk -- you've decided for yours=
elf what I am trying to present and no amount of arguing can cause you to b=
udge. I can only give up :-)</div></div></div></div></blockquote><div><br>M=
aybe because what you are trying to present changes with every post you mak=
e. Sometimes you say that we don't need `co_await` and instead use `co_=
noawait` or some such. Sometimes you say that we'd still have `co_await=
`. Sometimes you say that you just want inlining with no changes to anythin=
g else. Sometimes you say that a coroutine function is an object with some =
special properties that you never fully define.<br><br>It's impossible =
to talk concretely about a nebulous, moving target. All I can do is look at=
the code you present and try to deduce from it what you're trying to d=
o.<br><br>For example, let's look at this piece of code:<br><br><div st=
yle=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 18=
7); border-style: solid; border-width: 1px; overflow-wrap: break-word;" cla=
ss=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint=
"><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 =C2=A0 c=
orotuine </span><span style=3D"color: #008;" class=3D"styled-by-prettify">v=
oid</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> coro_f=
oo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{...}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 awaita=
ble</span><span style=3D"color: #080;" class=3D"styled-by-prettify"><voi=
d></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> bar<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> c=
b </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">new</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> coro_foo</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(*</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">cb</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">)();</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span></div></code></div><br>I can only =
hypothesize as to what this code is actually doing. You're invoking the=
`new` operator on what appears to be a value of type `void`. But since you=
've talked about coroutines exposing some kind of object to the user, I=
assume that using `()` on an identifier that is a coroutine function yield=
s some kind of object. Or perhaps `coro_foo` is grammatically a typename (i=
n which case, coroutines cannot be overloaded). Either one would work.<br><=
br>So there's this object that got heap allocated. And then you derefer=
ence the pointer to it, and invoke its `operator()` overload, returning the=
result of it. What does that do?<br><br>Again, I can only guess. There'=
;s a heap object that represents a coroutine that has not yet started execu=
tion. You invoke `operator()` on it, and return the result of that, constru=
cting a thing called `awaitable<void>`. So=C2=A0 I'm guessing thi=
s expression kicks off the coroutine. But does it actually invoke the corou=
tine function at that point?<br><br>What does the operator() return? Is it =
in some way related to `(*cb)`? And if not, how does `cb` get deleted?<br><=
br>None of that is well-defined.<br><br>So here's an idea: write out an=
<i>actual proposal</i>. Not vague ideas, but a fully-fleshed out design. A=
nd I mean something that is a fully defined as the current Coroutines TS. I=
should be able to read your proposal, look at any code that uses it, and k=
now exactly what every expression is and how it will behave. And right now,=
I cannot say that about anything you've suggested.<br><br>I want to st=
op playing 20 questions with you about what you want. Lay out the entire sc=
heme.<br><br>And no; simply saying "be inline and clearly mark them as=
coroutines" is not that. The above code is <i>very far</i> from that.=
<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/20b6d180-e4dc-4601-8afa-af0ece50a312%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/20b6d180-e4dc-4601-8afa-af0ece50a312=
%40isocpp.org</a>.<br />
------=_Part_6622_797572630.1520637268808--
------=_Part_6621_348091832.1520637268807--
.