Topic: comment on n4244
Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Thu, 23 Oct 2014 21:54:49 -0700 (PDT)
Raw View
------=_Part_1041_749916165.1414126489583
Content-Type: text/plain; charset=UTF-8
Hello,
WARNING: This question is potentially stupid.
why wanted<T> function in resumable lambdas returns a pointer, and not a
reference?
I think the need to indirection is superfluous, unless I am missing
something.
Regards
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1041_749916165.1414126489583
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hello,<div><br></div><div>WARNING: This question is potent=
ially stupid.</div><div><br></div><div>why wanted<T> function in resu=
mable lambdas returns a pointer, and not a reference?</div><div>I think the=
need to indirection is superfluous, unless I am missing something.</div><d=
iv><br></div><div><br></div><div>Regards</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1041_749916165.1414126489583--
.
Author: Jeremy Maitin-Shepard <jeremy@jeremyms.com>
Date: Thu, 23 Oct 2014 23:52:39 -0700 (PDT)
Raw View
------=_Part_1128_207985448.1414133559773
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, October 23, 2014 9:54:49 PM UTC-7, Germ=C3=A1n Diago wrote:
>
> why wanted<T> function in resumable lambdas returns a pointer, and not a=
=20
> reference?
> I think the need to indirection is superfluous, unless I am missing=20
> something.
>
In the example implementation on page 17, wanted<T> is defined to return=20
nullptr if the current state is not expected a T. Whether this runtime=20
check should be performed is a matter of debate, I think.
Related to this, though, it seems to me the requirement that the wanted=20
type be default constructible could be dropped. The caller could be=20
responsible for constructing the value, and the integer state variable=20
could be used to track whether it has been constructed yet. The=20
wanted_type could remain, but it would probably make sense to replace:
*f.wanted<T>() =3D T(args...);
with
f.wanted<T>(args...);
The wanted template would take care of constructing the wanted argument in=
=20
place from the specified arguments, and updating the state. Potentially it=
=20
would useful to have:
f.invoke<T>(args...); // equivalent to: f.wanted<T>(args...); f();
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1128_207985448.1414133559773
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, October 23, 2014 9:54:49 PM UTC-7, Germ=C3=A1=
n Diago 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"=
>why wanted<T> function in resumable lambdas returns a pointer, and n=
ot a reference?<div>I think the need to indirection is superfluous, unless =
I am missing something.</div></div></blockquote><div><br>In the example imp=
lementation on page 17, wanted<T> is defined to return nullptr if the=
current state is not expected a T. Whether this runtime check should=
be performed is a matter of debate, I think.<br><br><br>Related to this, t=
hough, it seems to me the requirement that the wanted type be=20
default constructible could be dropped. The caller could be responsib=
le
for constructing the value, and the integer state variable could be=20
used to track whether it has been constructed yet. The wanted_type co=
uld remain, but it would probably make sense to replace:<br><br>*f.wanted&l=
t;T>() =3D T(args...);<br><br>with<br><br>f.wanted<T>(args...);<br=
><br>The wanted template would take care of constructing the wanted argumen=
t in place from the specified arguments, and updating the state. Pote=
ntially it would useful to have:<br><br>f.invoke<T>(args...); &n=
bsp; // equivalent to: f.wanted<T>(args...); f();<br><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1128_207985448.1414133559773--
.
Author: contact@ncomputers.org
Date: Thu, 23 Oct 2014 23:57:50 -0700 (PDT)
Raw View
------=_Part_875_559277814.1414133870069
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Germ=C3=A1n,
I have very little experience with lambdas, but I learnt that a reference=
=20
is a pointer, so I suppose, that they would be equivalent.
Am Donnerstag, 23. Oktober 2014 23:54:49 UTC-5 schrieb Germ=C3=A1n Diago:
>
> Hello,
>
> WARNING: This question is potentially stupid.
>
> why wanted<T> function in resumable lambdas returns a pointer, and not a=
=20
> reference?
> I think the need to indirection is superfluous, unless I am missing=20
> something.
>
>
> Regards
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_875_559277814.1414133870069
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Germ=C3=A1n,<br><br>I have very little experience with lam=
bdas, but I learnt that a reference is a pointer, so I suppose, that they w=
ould be equivalent.<br><br>Am Donnerstag, 23. Oktober 2014 23:54:49 UTC-5 s=
chrieb Germ=C3=A1n Diago:<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">Hello,<div><br></div><div>WARNING: This question is potentially=
stupid.</div><div><br></div><div>why wanted<T> function in resumable=
lambdas returns a pointer, and not a reference?</div><div>I think the need=
to indirection is superfluous, unless I am missing something.</div><div><b=
r></div><div><br></div><div>Regards</div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_875_559277814.1414133870069--
.
Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Fri, 24 Oct 2014 00:03:33 -0700 (PDT)
Raw View
------=_Part_1106_1907216618.1414134213118
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
El viernes, 24 de octubre de 2014 13:57:50 UTC+7, con...@ncomputers.org=20
escribi=C3=B3:
>
> Germ=C3=A1n,
>
> I have very little experience with lambdas, but I learnt that a reference=
=20
> is a pointer, so I suppose, that they would be equivalent.
>
> Except for the fact that references cannot be null and need a explicit=20
dereference. Anyway, given the explanation above, which is that it can=20
return null, I see at least one reason now.=20
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1106_1907216618.1414134213118
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>El viernes, 24 de octubre de 2014 13:57:50 UTC+7, =
con...@ncomputers.org escribi=C3=B3:<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">Germ=C3=A1n,<br><br>I have very little experience w=
ith lambdas, but I learnt that a reference is a pointer, so I suppose, that=
they would be equivalent.<br><br></div></blockquote><div>Except for the fa=
ct that references cannot be null and need a explicit dereference. Anyway, =
given the explanation above, which is that it can return null, I see at lea=
st one reason now. </div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1106_1907216618.1414134213118--
.
Author: chris.kohlhoff@gmail.com
Date: Fri, 24 Oct 2014 00:07:17 -0700 (PDT)
Raw View
------=_Part_1132_259323403.1414134437629
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hi Germ=C3=A1n,
On Friday, October 24, 2014 3:54:49 PM UTC+11, Germ=C3=A1n Diago wrote:
>
> Hello,
>
> WARNING: This question is potentially stupid.
>
> why wanted<T> function in resumable lambdas returns a pointer, and not a=
=20
> reference?
> I think the need to indirection is superfluous, unless I am missing=20
> something.
>
Please see section 12.4's description of wanted's behaviour. It is=20
intended to be similar to std::function's target() and target_type().
Cheers,
Chris
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1132_259323403.1414134437629
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Germ=C3=A1n,<br><br>On Friday, October 24, 2014 3:=
54:49 PM UTC+11, Germ=C3=A1n Diago wrote:<blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr">Hello,<div><br></div><div>WARNING: This questio=
n is potentially stupid.</div><div><br></div><div>why wanted<T> funct=
ion in resumable lambdas returns a pointer, and not a reference?</div><div>=
I think the need to indirection is superfluous, unless I am missing somethi=
ng.</div></div></blockquote><div><br></div><div> Please see section 12=
..4's description of wanted's behaviour. It is intended to be similar to std=
::function's target() and target_type().</div><div><br></div><div>Cheers,</=
div><div>Chris</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1132_259323403.1414134437629--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 24 Oct 2014 00:17:52 -0700 (PDT)
Raw View
------=_Part_1149_1708738290.1414135072442
Content-Type: text/plain; charset=UTF-8
Hi Chris:
I have another question. How would a solution to same fringe (described in
N9835) problem will look in N4244 coroutines.
Essentially, we are trying to flatten the trees and compare the resulting
sequences.
Something like this:
bool same_fringe(node* tree1, node* tree2)
{
auto seq1 = flatten(tree1);
auto seq2 = flatten(tree2);
return equal(begin(seq1), end(seq1), begin(seq2), end(seq2));
}
where flatten is defined as:
auto flatten(node* n) { '' N4134 coroutines
if (n == nullptr) return;
yield flatten(n->left);
yield n->value;
yield flatten(n->right);
}
How flatten would look using N4244 coroutines?
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1149_1708738290.1414135072442
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi Chris:<br><br>I have another question. How would a=
solution to same fringe (described in N9835) problem will look in N4244 co=
routines.</div><div>Essentially, we are trying to flatten the trees and com=
pare the resulting sequences.</div><div><br>Something like this:</div><div>=
<br></div><div>
<p style=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; margin-l=
eft: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break: normal; lang=
uage: en-US; mso-line-break-override: none; punctuation-wrap: hanging;"><fo=
nt size=3D"2"><span style=3D"background: white; color: blue; font-family: C=
onsolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-them=
e-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: whit=
e; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-text=
fill-fill-color: blue; mso-style-textfill-fill-alpha: 100.0%;">bool</span><=
span style=3D"background: white; color: black; font-family: Consolas; langu=
age: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-=
fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-ke=
rning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-colo=
r: black; mso-style-textfill-fill-alpha: 100.0%;"> </span><span style=3D"ba=
ckground: white; color: black; font-family: Consolas; language: en-US; mso-=
ascii-font-family: Consolas; mso-fareast-theme-font: minor-fareast; mso-bid=
i-theme-font: minor-bidi; mso-highlight: white; mso-font-kerning: 12.0pt; m=
so-style-textfill-type: solid; mso-style-textfill-fill-color: black; mso-st=
yle-textfill-fill-alpha: 100.0%;">same_fringe</span><span style=3D"backgrou=
nd: white; color: black; font-family: Consolas; language: en-US; mso-ascii-=
font-family: Consolas; mso-fareast-theme-font: minor-fareast; mso-bidi-them=
e-font: minor-bidi; mso-highlight: white; mso-font-kerning: 12.0pt; mso-sty=
le-textfill-type: solid; mso-style-textfill-fill-color: black; mso-style-te=
xtfill-fill-alpha: 100.0%;">(node* tree1, node* tree2)</span></font></p><fo=
nt size=3D"2">
</font><p style=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; m=
argin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break: norma=
l; language: en-US; mso-line-break-override: none; punctuation-wrap: hangin=
g;"><span style=3D"background: white; color: black; font-family: Consolas; =
language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: m=
inor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-fo=
nt-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill=
-color: black; mso-style-textfill-fill-alpha: 100.0%;"><font size=3D"2">{</=
font></span></p><font size=3D"2">
</font><p style=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; m=
argin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break: norma=
l; language: en-US; mso-line-break-override: none; punctuation-wrap: hangin=
g;"><font size=3D"2"><span style=3D"background: white; color: blue; font-fa=
mily: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-farea=
st-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highligh=
t: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-sty=
le-textfill-fill-color: blue; mso-style-textfill-fill-alpha: 100.0%;"><span=
style=3D"mso-spacerun: yes;"> </span>auto</span><span st=
yle=3D"background: white; color: black; font-family: Consolas; language: en=
-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-fareast=
; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-kerning: =
12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-color: blac=
k; mso-style-textfill-fill-alpha: 100.0%;">
</span><span style=3D"background: white; color: black; font-family: Consola=
s; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font=
: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso=
-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-f=
ill-color: black; mso-style-textfill-fill-alpha: 100.0%;">seq1 =3D flatten(=
tree1);</span></font></p><font size=3D"2">
</font><p style=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; m=
argin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break: norma=
l; language: en-US; mso-line-break-override: none; punctuation-wrap: hangin=
g;"><font size=3D"2"><span style=3D"background: white; color: blue; font-fa=
mily: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-farea=
st-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highligh=
t: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-sty=
le-textfill-fill-color: blue; mso-style-textfill-fill-alpha: 100.0%;"><span=
style=3D"mso-spacerun: yes;"> </span>auto</span><span st=
yle=3D"background: white; color: black; font-family: Consolas; language: en=
-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-fareast=
; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-kerning: =
12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-color: blac=
k; mso-style-textfill-fill-alpha: 100.0%;">
</span><span style=3D"background: white; color: black; font-family: Consola=
s; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font=
: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso=
-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-f=
ill-color: black; mso-style-textfill-fill-alpha: 100.0%;">seq2 =3D flatten(=
tree2);</span></font></p><font size=3D"2">
</font><p style=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; m=
argin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break: norma=
l; language: en-US; mso-line-break-override: none; punctuation-wrap: hangin=
g;"><font size=3D"2"><span style=3D"background: white; color: blue; font-fa=
mily: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-farea=
st-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highligh=
t: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-sty=
le-textfill-fill-color: blue; mso-style-textfill-fill-alpha: 100.0%;"><span=
style=3D"mso-spacerun: yes;"> </span>return</span><span =
style=3D"background: white; color: black; font-family: Consolas; language: =
en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-farea=
st; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-kerning=
: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-color: bl=
ack; mso-style-textfill-fill-alpha: 100.0%;">
</span><span style=3D"background: white; color: black; font-family: Consola=
s; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font=
: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso=
-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-f=
ill-color: black; mso-style-textfill-fill-alpha: 100.0%;">equal(begin(seq1)=
, end(seq1</span><span style=3D"background: white; color: black; font-famil=
y: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-=
theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: =
white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-=
textfill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;">), begi=
n(seq2), end(seq2));</span></font></p><font size=3D"2">
</font><p style=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; m=
argin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break: norma=
l; language: en-US; mso-line-break-override: none; punctuation-wrap: hangin=
g;"><span style=3D"background: white; color: black; font-family: Consolas; =
language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: m=
inor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-fo=
nt-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill=
-color: black; mso-style-textfill-fill-alpha: 100.0%;"><font size=3D"2">}</=
font></span></p><p style=3D"text-align: left; margin-top: 0pt; margin-botto=
m: 0pt; margin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-bre=
ak: normal; language: en-US; mso-line-break-override: none; punctuation-wra=
p: hanging;"><span style=3D"background: white; color: black; font-family: C=
onsolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-them=
e-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: whit=
e; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-text=
fill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;"><font size=
=3D"2"><br></font></span></p><p style=3D"text-align: left; margin-top: 0pt;=
margin-bottom: 0pt; margin-left: 0in; unicode-bidi: embed; direction: ltr;=
-ms-word-break: normal; language: en-US; mso-line-break-override: none; pu=
nctuation-wrap: hanging;"><span style=3D"background: white; color: black; f=
ont-family: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso=
-fareast-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-hi=
ghlight: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; m=
so-style-textfill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;=
"><font size=3D"2">where flatten is defined as:</font></span></p><p style=
=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; margin-left: 0in=
; unicode-bidi: embed; direction: ltr; -ms-word-break: normal; language: en=
-US; mso-line-break-override: none; punctuation-wrap: hanging;"><br></p><sp=
an style=3D"background: white; color: black; font-family: Consolas; languag=
e: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-fa=
reast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-kern=
ing: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-color:=
black; mso-style-textfill-fill-alpha: 100.0%;"><font size=3D"2"><p style=
=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; margin-left: 0in=
; unicode-bidi: embed; direction: ltr; -ms-word-break: normal; language: en=
-US; mso-line-break-override: none; punctuation-wrap: hanging;"><font size=
=3D"2"><span style=3D"background: white; color: blue; font-family: Consolas=
; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font:=
minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-=
font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fi=
ll-color: blue; mso-style-textfill-fill-alpha: 100.0%;">auto</span><span st=
yle=3D"background: white; color: black; font-family: Consolas; language: en=
-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-fareast=
; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-kerning: =
12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-color: blac=
k; mso-style-textfill-fill-alpha: 100.0%;"> </span><span style=3D"backgroun=
d: white; color: black; font-family: Consolas; language: en-US; mso-ascii-f=
ont-family: Consolas; mso-fareast-theme-font: minor-fareast; mso-bidi-theme=
-font: minor-bidi; mso-highlight: white; mso-font-kerning: 12.0pt; mso-styl=
e-textfill-type: solid; mso-style-textfill-fill-color: black; mso-style-tex=
tfill-fill-alpha: 100.0%;">flatten(node* n) </span><span style=3D"backgroun=
d: white; color: black; font-family: Consolas; language: en-US; mso-ascii-f=
ont-family: Consolas; mso-fareast-theme-font: minor-fareast; mso-bidi-theme=
-font: minor-bidi; mso-highlight: white; mso-font-kerning: 12.0pt; mso-styl=
e-textfill-type: solid; mso-style-textfill-fill-color: black; mso-style-tex=
tfill-fill-alpha: 100.0%;">{ '' N4134 coroutines</span></font></p><p style=
=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; margin-left: 0in=
; unicode-bidi: embed; direction: ltr; -ms-word-break: normal; language: en=
-US; mso-line-break-override: none; punctuation-wrap: hanging;"><font size=
=3D"2"><span style=3D"background: white; color: blue; font-family: Consolas=
; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font:=
minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-=
font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fi=
ll-color: blue; mso-style-textfill-fill-alpha: 100.0%;"><span style=3D"mso-=
spacerun: yes;"> </span>if </span><span style=3D"backgrou=
nd: white; color: black; font-family: Consolas; language: en-US; mso-ascii-=
font-family: Consolas; mso-fareast-theme-font: minor-fareast; mso-bidi-them=
e-font: minor-bidi; mso-highlight: white; mso-font-kerning: 12.0pt; mso-sty=
le-textfill-type: solid; mso-style-textfill-fill-color: black; mso-style-te=
xtfill-fill-alpha: 100.0%;">(</span><span style=3D"background: white; color=
: black; font-family: Consolas; language: en-US; mso-ascii-font-family: Con=
solas; mso-fareast-theme-font: minor-fareast; mso-bidi-theme-font: minor-bi=
di; mso-highlight: white; mso-font-kerning: 12.0pt; mso-style-textfill-type=
: solid; mso-style-textfill-fill-color: black; mso-style-textfill-fill-alph=
a: 100.0%;">n =3D=3D </span><span style=3D"background: white; color: blue; =
font-family: Consolas; language: en-US; mso-ascii-font-family: Consolas; ms=
o-fareast-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-h=
ighlight: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; =
mso-style-textfill-fill-color: blue; mso-style-textfill-fill-alpha: 100.0%;=
">nullptr</span><span style=3D"background: white; color: black; font-family=
: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-t=
heme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: w=
hite; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-t=
extfill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;">) </span=
><span style=3D"background: white; color: blue; font-family: Consolas; lang=
uage: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor=
-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-k=
erning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-col=
or: blue; mso-style-textfill-fill-alpha: 100.0%;">return</span></font><font=
size=3D"2"><span style=3D"background: white; color: black; font-family: Co=
nsolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme=
-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white=
; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textf=
ill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;">;<br>
<span style=3D"mso-spacerun: yes;"> </span></span><span s=
tyle=3D"background: white; color: blue; font-family: Consolas; language: en=
-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font: minor-fareast=
; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso-font-kerning: =
12.0pt; mso-style-textfill-type: solid; mso-style-textfill-fill-color: blue=
; mso-style-textfill-fill-alpha: 100.0%;">yield
</span><span style=3D"background: white; color: black; font-family: Consola=
s; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-font=
: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; mso=
-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-f=
ill-color: black; mso-style-textfill-fill-alpha: 100.0%;">flatten(n->lef=
t);</span></font></p><p style=3D"text-align: left; margin-top: 0pt; margin-=
bottom: 0pt; margin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-wor=
d-break: normal; language: en-US; mso-line-break-override: none; punctuatio=
n-wrap: hanging;"><font size=3D"2"><span style=3D"background: white; color:=
blue; font-family: Consolas; language: en-US; mso-ascii-font-family: Conso=
las; mso-fareast-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi=
; mso-highlight: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: =
solid; mso-style-textfill-fill-color: blue; mso-style-textfill-fill-alpha: =
100.0%;"><span style=3D"mso-spacerun: yes;"> </span>yield=
</span><span style=3D"background: white; color: black; font-family: Consol=
as; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-theme-fon=
t: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: white; ms=
o-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-textfill-=
fill-color: black; mso-style-textfill-fill-alpha: 100.0%;">n->value;</sp=
an></font></p><p style=3D"text-align: left; margin-top: 0pt; margin-bottom:=
0pt; margin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-break=
: normal; language: en-US; mso-line-break-override: none; punctuation-wrap:=
hanging;"><font size=3D"2"><span style=3D"background: white; color: blue; =
font-family: Consolas; language: en-US; mso-ascii-font-family: Consolas; ms=
o-fareast-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-h=
ighlight: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; =
mso-style-textfill-fill-color: blue; mso-style-textfill-fill-alpha: 100.0%;=
"><span style=3D"mso-spacerun: yes;"> </span></span><span style=3D"bac=
kground: white; color: blue; font-family: Consolas; language: en-US; mso-as=
cii-font-family: Consolas; mso-fareast-theme-font: minor-fareast; mso-bidi-=
theme-font: minor-bidi; mso-highlight: white; mso-font-kerning: 12.0pt; mso=
-style-textfill-type: solid; mso-style-textfill-fill-color: blue; mso-style=
-textfill-fill-alpha: 100.0%;"><span style=3D"mso-spacerun: yes;"> &nb=
sp; </span>yield </span><span style=3D"background: white; color: black; fon=
t-family: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-f=
areast-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-high=
light: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso=
-style-textfill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;">=
flatten(n-</span><span style=3D"background: white; color: black; font-famil=
y: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareast-=
theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight: =
white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-style-=
textfill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;">>rig=
ht);</span></font></p><p style=3D"text-align: left; margin-top: 0pt; margin=
-bottom: 0pt; margin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-wo=
rd-break: normal; language: en-US; mso-line-break-override: none; punctuati=
on-wrap: hanging;"><span style=3D"background: white; color: black; font-fam=
ily: Consolas; language: en-US; mso-ascii-font-family: Consolas; mso-fareas=
t-theme-font: minor-fareast; mso-bidi-theme-font: minor-bidi; mso-highlight=
: white; mso-font-kerning: 12.0pt; mso-style-textfill-type: solid; mso-styl=
e-textfill-fill-color: black; mso-style-textfill-fill-alpha: 100.0%;"><font=
size=3D"2">}</font></span></p><p style=3D"text-align: left; margin-top: 0p=
t; margin-bottom: 0pt; margin-left: 0in; unicode-bidi: embed; direction: lt=
r; -ms-word-break: normal; language: en-US; mso-line-break-override: none; =
punctuation-wrap: hanging;">
<br></p></font><p style=3D"text-align: left; margin-top: 0pt; margin-bottom=
: 0pt; margin-left: 0in; unicode-bidi: embed; direction: ltr; -ms-word-brea=
k: normal; language: en-US; mso-line-break-override: none; punctuation-wrap=
: hanging;">How flatten would look using N4244 coroutines?</p></span><p sty=
le=3D"text-align: left; margin-top: 0pt; margin-bottom: 0pt; margin-left: 0=
in; unicode-bidi: embed; direction: ltr; -ms-word-break: normal; language: =
en-US; mso-line-break-override: none; punctuation-wrap: hanging;"><br></p>
</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1149_1708738290.1414135072442--
.
Author: chris.kohlhoff@gmail.com
Date: Fri, 24 Oct 2014 00:18:07 -0700 (PDT)
Raw View
------=_Part_18_653242931.1414135087401
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hi Jeremy,
On Friday, October 24, 2014 5:52:39 PM UTC+11, Jeremy Maitin-Shepard wrote:
>
> On Thursday, October 23, 2014 9:54:49 PM UTC-7, Germ=C3=A1n Diago wrote:
>>
>> why wanted<T> function in resumable lambdas returns a pointer, and not a=
=20
>> reference?
>> I think the need to indirection is superfluous, unless I am missing=20
>> something.
>>
>
> In the example implementation on page 17, wanted<T> is defined to return=
=20
> nullptr if the current state is not expected a T. Whether this runtime=
=20
> check should be performed is a matter of debate, I think.
>
There's no additional runtime cost due to checking the type. You already=20
have to check the state to be able to return the correct wanted variable.=
=20
The type check is really a compile time check, and is facilitated by the=20
use of __wanted_tag in the page 17 example.
=20
> Related to this, though, it seems to me the requirement that the wanted=
=20
> type be default constructible could be dropped. The caller could be=20
> responsible for constructing the value, and the integer state variable=20
> could be used to track whether it has been constructed yet. The=20
> wanted_type could remain, but it would probably make sense to replace:
>
> *f.wanted<T>() =3D T(args...);
>
> with
>
> f.wanted<T>(args...);
>
I originally had this approach, but discarded it because it makes writing=
=20
runtime polymorphic wrappers difficult. Right now we can use=20
f.wanted<void>() in a polymorphic context.
Note that, as I mentioned in an earlier post, I'm thinking of discarding=20
the "yield (type-id)" syntax altogether. The equivalent can be achieved=20
using a sub generator library type. This would also lift the restriction=20
that T be DefaultConstructible, though it would still require that T have=
=20
been constructed prior to being returned by wanted<T>().
Cheers,
Chris
=20
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_18_653242931.1414135087401
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Jeremy,<br><br>On Friday, October 24, 2014 5:52:39 PM U=
TC+11, Jeremy Maitin-Shepard 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 Thursday, October 23, 2014 9:54:49 PM UTC-7, Germ=
=C3=A1n Diago 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=
">why wanted<T> function in resumable lambdas returns a pointer, and =
not a reference?<div>I think the need to indirection is superfluous, unless=
I am missing something.</div></div></blockquote><div><br>In the example im=
plementation on page 17, wanted<T> is defined to return nullptr if th=
e current state is not expected a T. Whether this runtime check shoul=
d be performed is a matter of debate, I think.<br></div></div></blockquote>=
<div><br></div><div>There's no additional runtime cost due to checking the =
type. You already have to check the state to be able to return the correct =
wanted variable. The type check is really a compile time check, and is faci=
litated by the use of __wanted_tag in the page 17 example.</div><div> =
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Re=
lated to this, though, it seems to me the requirement that the wanted type =
be=20
default constructible could be dropped. The caller could be responsib=
le
for constructing the value, and the integer state variable could be=20
used to track whether it has been constructed yet. The wanted_type co=
uld remain, but it would probably make sense to replace:<br><br>*f.wanted&l=
t;T>() =3D T(args...);<br><br>with<br><br>f.wanted<T>(args...);<br=
></div></div></blockquote><div><br></div><div>I originally had this approac=
h, but discarded it because it makes writing runtime polymorphic wrappers d=
ifficult. Right now we can use f.wanted<void>() in a polymorphic cont=
ext.</div><div><br></div><div>Note that, as I mentioned in an earlier post,=
I'm thinking of discarding the "yield (type-id)" syntax altogether. The eq=
uivalent can be achieved using a sub generator library type. This would als=
o lift the restriction that T be DefaultConstructible, though it would stil=
l require that T have been constructed prior to being returned by wanted<=
;T>().</div><div><br></div><div>Cheers,</div><div>Chris</div><div> =
</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_18_653242931.1414135087401--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 24 Oct 2014 00:46:08 -0700 (PDT)
Raw View
Correction to my previous question to Chris. I meant N3985. Oliver&Nat's paper on coroutines that described same fringe problem. I'd like to understand how the solution will look under your proposal
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Fri, 24 Oct 2014 02:55:58 -0700 (PDT)
Raw View
------=_Part_1523_1855974279.1414144558143
Content-Type: text/plain; charset=UTF-8
On Friday, October 24, 2014 8:46:08 AM UTC+1, Gor Nishanov wrote:
>
> Correction to my previous question to Chris. I meant N3985. Oliver&Nat's
> paper on coroutines that described same fringe problem. I'd like to
> understand how the solution will look under your proposal
"Same Fringe" requires stackfull coroutines to be implemented efficiently
(it needs to yield deep inside a recursive tree visit). With stackless
generators (like those of python, C# and those proposed for C++ other than
Oliver&Nat proposal), you would need to yield at every stack level but it
would in practice make yielding an O(log n) operation, changing the
complexity of the algorithm. Within N4244 I guess you would use 'yield
from'; you would probably need to explicitly heap allocate (and type erase)
frames to support arbitrary recursion depth (in practice reifying the call
stack), but I might be wrong here.
Really, the various generator proposals are about implementing very
efficient external iterators for linear data strucutres and simplifying the
Continuation Passing Style required for tipical async code without the
memory cost keeping around a whole stack.
Personally I would like to see both styles in the standard: full Oliver&Nat
coroutines for the general case and 0-overhead Chris' style generators for
iteration and async continuations that do not require keeping around the
full stack. Because of the simplicity I think Chris' work has more chances
to get into the standard.
There is at least another use case for coroutines/generators: Cilk style
parent stealing; I think that can also be implemented with 4244, without
additional compiler support.
-- gpd
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1523_1855974279.1414144558143
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Friday, October 24, 2014 8:46:08 AM UTC+1, Gor =
Nishanov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Correction to m=
y previous question to Chris. I meant N3985. Oliver&Nat's paper on coro=
utines that described same fringe problem. I'd like to understand how the s=
olution will look under your proposal</blockquote><div><br>"Same Fringe" re=
quires stackfull coroutines to be implemented efficiently (it needs to yiel=
d deep inside a recursive tree visit). With stackless generators (like thos=
e of python, C# and those proposed for C++ other than Oliver&Nat propos=
al), you would need to yield at every stack level but it would in practice =
make yielding an O(log n) operation, changing the complexity of the algorit=
hm. Within N4244 I guess you would use 'yield from'; you would probably nee=
d to explicitly heap allocate (and type erase) frames to support arbitrary =
recursion depth (in practice reifying the call stack), but I might be wrong=
here.<br><br>Really, the various generator proposals are about implementin=
g very efficient external iterators for linear data strucutres and simplify=
ing the Continuation Passing Style required for tipical async code without =
the memory cost keeping around a whole stack.<br><br>Personally I would lik=
e to see both styles in the standard: full Oliver&Nat coroutines for th=
e general case and 0-overhead Chris' style generators for iteration and asy=
nc continuations that do not require keeping around the full stack. Because=
of the simplicity I think Chris' work has more chances to get into the sta=
ndard.<br><br>There is at least another use case for coroutines/generators:=
Cilk style parent stealing; I think that can also be implemented with 4244=
, without additional compiler support.<br><br>-- gpd<br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1523_1855974279.1414144558143--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 24 Oct 2014 06:44:04 -0700 (PDT)
Raw View
------=_Part_1321_977816604.1414158244755
Content-Type: text/plain; charset=UTF-8
Hi Giovanni:
> "Same Fringe" requires stackfull coroutines to be implemented efficiently
> (it needs to yield deep inside a recursive tree visit). With stackless
> generators (like those of python, C# and those proposed for C++ other than
> Oliver&Nat proposal), you would need to yield at every stack level but it
> would in practice make yielding an O(log n) operation,
>
I don't think so. It depends how you implement yield a generator. In a
generators, supported by N4134, when you yield not a value but another
generator, it treats it as await until that generator is finished, thus it
is always the very top generator that keeps yielding values to the user,
and when the user pulls the value from the generator it goes straight back
to the very top one. It does not walk the generator "stack" to do that.
Stackful do have cheaper recursive invocations because they have normal
stack, but it is compensated by more expensive context switch, thus making
each yield more expensive.
Quick test using boost::context vs N4134 (note we did not implement yet any
coroutine specific optimizations and our ventual codegen will be much
better. Remember when Stephanov did STL it was not zero-overhead on any
existing compiler).
Anyway:
This is what is being tested:
generator<int> GoDeep(int depth) {
yield depth;
if (depth > 0) yield GoDeep(depth-1);
}
compared to:
void traverse(int depth, asymmetric_coroutine<int>::push_type & out) {
out(depth);
if (depth > 0) traverse(depth - 1, out);
}
asymmetric_coroutine<int>::pull_type recurse(int n) {
return asymmetric_coroutine<int>::pull_type(
[=](asymmetric_coroutine<int>::push_type& sink) {
traverse(n, sink); },
attributes(flag_fpu_t::fpu_not_preserved));
}
I call GoDeep(10 * 1000 * 1000) and measure.
Stackful: 0.417057 secs: yields 10000000 values 41.705700ns per each
Stackless: 0.517368 secs: yields 10000001 values 51.736836ns per each
Again, with better codegen we will be beating stackful on recursive
problems when higher recursive call overhead of stackless is less than
higher yield cost on stackful.
> frames to support arbitrary recursion depth (in practice reifying the call
> stack), but I might be wrong here.
>
Yeah. I really want Chris to chime in, and hopefully provide a full
implementation for GoDeep()
> Personally I would like to see both styles in the standard: full
> Oliver&Nat coroutines for the general case and 0-overhead Chris' style
> generators for iteration
>
I think stackless can take the coroutine niche. I showed about that
stackles can match stackful in the problem domain when stackful is king.
However, I do believe that machinery powering N9835 (aka boost::context /
fibers) is valuable as it can serve as a foundation for cooperative user
mode threads in C++ / fibers
> and async continuations that do not require keeping around the full stack.
> Because of the simplicity I think Chris' work has more chances to get into
> the standard.
>
:-) As you can guess, I hold different opinion on this particular point.
> There is at least another use case for coroutines/generators: Cilk style
> parent stealing; I think that can also be implemented with 4244, without
> additional compiler support.
>
Have you seen parent stealing example from N4134?
spawnable<int> fib(int n) {
if (n < 2) return n;
return await(fib(n - 1) + fib(n - 2));
}
Here is another example, I will be curious if N4244 can tackle?
From N4134:
Reactive Streams
Resumable functions can be used as producers, consumers and transformers of
reactive streams in recently rediscovered [Rx, ReactiveX, RxAtNetflix]
functional reactive programming [FRP].
As a consumer (utilizing await-for statement proposed by this paper):
future<int> Sum(async_read_stream<int> & input)
{
int sum = 0;
for await (v : input)
{
sum += v;
}
return sum;
}
As a producer:
async_generator<int> Ticks()
{
for(int tick = 0;; ++tick) {
yield tick;
await sleep_for(1ms);
}
}
As a transformer: (adds a timestamp to every observed value)
template<class T>
async_generator<pair<T, *system_clock*::*time_point*>>
Timestamp(async_read_stream<T> S)
{
for await(v: S) yield {v, *system_clock*::now()};
}
Cheers,
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1321_977816604.1414158244755
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Giovanni:<br><div> </div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left=
-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: soli=
d;"><div dir=3D"ltr">"Same Fringe" requires stackfull coroutines to be impl=
emented efficiently (it needs to yield deep inside a recursive tree visit).=
With stackless generators (like those of python, C# and those proposed for=
C++ other than Oliver&Nat proposal), you would need to yield at every =
stack level but it would in practice make yielding an O(log n) operation, <=
/div></blockquote><div><br></div><div>I don't think so. It depends how you =
implement yield a generator. In a generators, supported by N4134, when you =
yield not a value but another generator, it treats it as await until that g=
enerator is finished, thus it is always the very top generator that keeps y=
ielding values to the user, and when the user pulls the value from the gene=
rator it goes straight back to the very top one. It does not walk the gener=
ator "stack" to do that.</div><div><br></div><div>Stackful do have cheaper =
recursive invocations because they have normal stack, but it is compensated=
by more expensive context switch, thus making each yield more expensive.</=
div><div><br></div><div>Quick test using boost::context vs N4134 (note we d=
id not implement yet any coroutine specific optimizations and our ventual c=
odegen will be much better. Remember when Stephanov did STL it was not zero=
-overhead on any existing compiler).</div><div><br></div><div>Anyway:</div>=
<div><br></div><div>This is what is being tested:</div><div><br></div><div>=
<p><font face=3D"Consolas" size=3D"2">generator<</font><font color=3D"#0=
000ff" face=3D"Consolas" size=3D"2">int</font><font face=3D"Consolas" size=
=3D"2">> GoDeep(</font><font color=3D"#0000ff" face=3D"Consolas" size=3D=
"2">int</font><font face=3D"Consolas" size=3D"2"> depth) {<br></font><font =
face=3D"Consolas" style=3D"font-family: Consolas;" size=3D"2"> =
</font><font color=3D"#0000ff" face=3D"Consolas" style=3D"font-family: Cons=
olas;">yield</font><span style=3D"font-family: Consolas;"> depth;<br></span=
><font face=3D"Consolas"> </font><font color=3D"#0000ff" face=
=3D"Consolas">if</font><font face=3D"Consolas"> (depth > 0) </font>=
<font color=3D"#0000ff" face=3D"Consolas" style=3D"font-family: Consolas;">=
yield</font><span style=3D"font-family: Consolas;"> </span><span style=
=3D"font-family: Consolas;">GoDeep(depth-1);<br></span><span style=3D"font-=
family: Consolas;">}</span></p><p><span style=3D"font-family: Consolas;">co=
mpared to:</span></p><p><font face=3D"Consolas">void traverse(</font><span =
style=3D"font-family: Consolas;">int depth, asymmetric_coroutine<int>=
::push_type & out) </span><span style=3D"font-family: Consolas;">{=
<br></span><span style=3D"font-family: Consolas;"> out(depth);=
<br></span><span style=3D"font-family: Consolas;"> if (depth &=
gt; 0) </span><span style=3D"font-family: Consolas;">traverse(depth - =
1, out);<br></span><span style=3D"font-family: Consolas;">}</span></p><p><s=
pan style=3D"font-family: Consolas;">asymmetric_coroutine<int>::pull_=
type recurse(int n) {<br></span><span style=3D"font-family: Consolas;">&nbs=
p; return asymmetric_coroutine<int>::pull_type(<br></span><span=
style=3D"font-family: Consolas;"> [=3D](asymmet=
ric_coroutine<int>::push_type& sink) { <br> &=
nbsp; traverse(n, sink); },<br></span><span style=3D"font-fami=
ly: Consolas;"> attributes(flag_fpu_t::fpu_not_preserved));<br=
></span><span style=3D"font-family: Consolas;">}</span></p><div>I call GoDe=
ep(10 * 1000 * 1000) and measure.</div><div><br></div><div>Stackful: 0=
..417057 secs: yields 10000000 values 41.705700ns per each</div><p><span sty=
le=3D"font-family: Consolas;">Stackless: 0.517368 secs: yields 10000001 val=
ues 51.736836ns per each</span><br></p></div><div>Again, with better codege=
n we will be beating stackful on recursive problems when higher recursive c=
all overhead of stackless is less than higher yield cost on stackful.</div>=
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">frames to su=
pport arbitrary recursion depth (in practice reifying the call stack), but =
I might be wrong here.<br></div></blockquote><div><br></div><div>Yeah. I re=
ally want Chris to chime in, and hopefully provide a full implementation fo=
r GoDeep()</div><div> </div><blockquote class=3D"gmail_quote" style=3D=
"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, =
204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"l=
tr">Personally I would like to see both styles in the standard: full Oliver=
&Nat coroutines for the general case and 0-overhead Chris' style genera=
tors for iteration </div></blockquote><div><br></div><div>I think stackless=
can take the coroutine niche. I showed about that stackles can match stack=
ful in the problem domain when stackful is king.</div><div><br></div><div>H=
owever, I do believe that machinery powering N9835 (aka boost::context / fi=
bers) is valuable as it can serve as a foundation for cooperative user mode=
threads in C++ / fibers</div><div> </div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-co=
lor: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"=
><div dir=3D"ltr">and async continuations that do not require keeping aroun=
d the full stack. Because of the simplicity I think Chris' work has more ch=
ances to get into the standard.<br></div></blockquote><div><br></div><div>:=
-) As you can guess, I hold different opinion on this particular point.</di=
v><div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0=
px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bor=
der-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">There is a=
t least another use case for coroutines/generators: Cilk style parent steal=
ing; I think that can also be implemented with 4244, without additional com=
piler support.<br></div></blockquote><div><br>Have you seen parent stealing=
example from N4134?</div><div><br></div><p class=3D"Code" style=3D"margin-=
left:.5in"><span style=3D"background-image: initial; background-attachment:=
initial; background-size: initial; background-origin: initial; background-=
clip: initial; background-position: initial; background-repeat: initial;">s=
pawnable<<span style=3D"color:blue">int</span>> fib(<span style=3D"co=
lor:blue">int</span> n) {<br></span> <span style=
=3D"color: blue;">if</span> (n < 2) <span style=3D"color: blue;">return<=
/span>
n;<br> <span style=3D"color: blue;">return</span>=
<span style=3D"color: blue;">await</span>(fib(n -
1) + fib(n - 2));<br>} </p><p class=3D"Code" style=3D"margin-left:.5in=
"><br></p><p class=3D"Code" style=3D"margin-left:.5in">Here is another exam=
ple, I will be curious if N4244 can tackle?</p><p class=3D"Code" style=3D"m=
argin-left:.5in">From N4134:</p><h3><a name=3D"_Toc400720928">Reactive Stre=
ams</a><o:p></o:p></h3>
<p class=3D"MsoNormal">Resumable functions can be used as producers, consum=
ers and
transformers of reactive streams in recently rediscovered [Rx, ReactiveX, R=
xAtNetflix]
functional reactive programming [FRP].<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p></o:p></p><p class=3D"MsoNormal">As a consumer =
(utilizing await-for statement proposed by
this paper):<br></p><p class=3D"MsoNormal"><o:p></o:p></p><p class=3D"MsoNo=
rmal" style=3D"margin-top:0in;margin-right:0in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-a=
lign:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: rgb(33, 111, 133); background-image: initial; background-atta=
chment: initial; background-size: initial; background-origin: initial; back=
ground-clip: initial; background-position: initial; background-repeat: init=
ial;">future</span><span style=3D"font-size: 9.5pt; font-family: Consolas; =
color: black; background-image: initial; background-attachment: initial; ba=
ckground-size: initial; background-origin: initial; background-clip: initia=
l; background-position: initial; background-repeat: initial;"><</span><s=
pan style=3D"font-size: 9.5pt; font-family: Consolas; color: blue; backgrou=
nd-image: initial; background-attachment: initial; background-size: initial=
; background-origin: initial; background-clip: initial; background-position=
: initial; background-repeat: initial;">int</span><span style=3D"font-size:=
9.5pt; font-family: Consolas; color: black; background-image: initial; bac=
kground-attachment: initial; background-size: initial; background-origin: i=
nitial; background-clip: initial; background-position: initial; background-=
repeat: initial;">> </span><span style=3D"font-size: 9.5pt; font-family:=
Consolas; color: rgb(136, 0, 0); background-image: initial; background-att=
achment: initial; background-size: initial; background-origin: initial; bac=
kground-clip: initial; background-position: initial; background-repeat: ini=
tial;">Sum</span><span style=3D"font-size: 9.5pt; font-family: Consolas; co=
lor: black; background-image: initial; background-attachment: initial; back=
ground-size: initial; background-origin: initial; background-clip: initial;=
background-position: initial; background-repeat: initial;">(</span><span s=
tyle=3D"font-size: 9.5pt; font-family: Consolas; color: rgb(33, 111, 133); =
background-image: initial; background-attachment: initial; background-size:=
initial; background-origin: initial; background-clip: initial; background-=
position: initial; background-repeat: initial;">async_read_stream</span><sp=
an style=3D"font-size: 9.5pt; font-family: Consolas; color: black; backgrou=
nd-image: initial; background-attachment: initial; background-size: initial=
; background-origin: initial; background-clip: initial; background-position=
: initial; background-repeat: initial;"><</span><span style=3D"font-size=
: 9.5pt; font-family: Consolas; color: blue; background-image: initial; bac=
kground-attachment: initial; background-size: initial; background-origin: i=
nitial; background-clip: initial; background-position: initial; background-=
repeat: initial;">int</span><span style=3D"font-size: 9.5pt; font-family: C=
onsolas; color: black; background-image: initial; background-attachment: in=
itial; background-size: initial; background-origin: initial; background-cli=
p: initial; background-position: initial; background-repeat: initial;">>=
& </span><span style=3D"font-size: 9.5pt; font-family: Consolas; color=
: navy; background-image: initial; background-attachment: initial; backgrou=
nd-size: initial; background-origin: initial; background-clip: initial; bac=
kground-position: initial; background-repeat: initial;">input</span><span s=
tyle=3D"font-size: 9.5pt; font-family: Consolas; color: black; background-i=
mage: initial; background-attachment: initial; background-size: initial; ba=
ckground-origin: initial; background-clip: initial; background-position: in=
itial; background-repeat: initial;">)<o:p></o:p></span></p><p class=3D"MsoN=
ormal" style=3D"margin-top:0in;margin-right:0in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-a=
lign:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: black; background-image: initial; background-attachment: init=
ial; background-size: initial; background-origin: initial; background-clip:=
initial; background-position: initial; background-repeat: initial;">{<o:p>=
</o:p></span></p><p class=3D"MsoNormal" style=3D"margin-top:0in;margin-righ=
t:0in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-a=
lign:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: black; background-image: initial; background-attachment: init=
ial; background-size: initial; background-origin: initial; background-clip:=
initial; background-position: initial; background-repeat: initial;"> =
</span><span style=3D"font-size: 9.5pt; font=
-family: Consolas; color: blue; background-image: initial; background-attac=
hment: initial; background-size: initial; background-origin: initial; backg=
round-clip: initial; background-position: initial; background-repeat: initi=
al;">int</span><span style=3D"font-size: 9.5pt; font-family: Consolas; colo=
r: black; background-image: initial; background-attachment: initial; backgr=
ound-size: initial; background-origin: initial; background-clip: initial; b=
ackground-position: initial; background-repeat: initial;"> sum =3D 0; <o:p>=
</o:p></span></p><p class=3D"MsoNormal" style=3D"margin-top:0in;margin-righ=
t:0in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-a=
lign:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: black; background-image: initial; background-attachment: init=
ial; background-size: initial; background-origin: initial; background-clip:=
initial; background-position: initial; background-repeat: initial;"> =
</span><span style=3D"font-size: 9.5pt; font=
-family: Consolas; color: blue; background-image: initial; background-attac=
hment: initial; background-size: initial; background-origin: initial; backg=
round-clip: initial; background-position: initial; background-repeat: initi=
al;">for</span><span style=3D"font-size: 9.5pt; font-family: Consolas; colo=
r: black; background-image: initial; background-attachment: initial; backgr=
ound-size: initial; background-origin: initial; background-clip: initial; b=
ackground-position: initial; background-repeat: initial;"> </span><span sty=
le=3D"font-size: 9.5pt; font-family: Consolas; color: blue; background-imag=
e: initial; background-attachment: initial; background-size: initial; backg=
round-origin: initial; background-clip: initial; background-position: initi=
al; background-repeat: initial;">await</span><span style=3D"font-size: 9.5p=
t; font-family: Consolas; color: black; background-image: initial; backgrou=
nd-attachment: initial; background-size: initial; background-origin: initia=
l; background-clip: initial; background-position: initial; background-repea=
t: initial;"> (</span><span style=3D"font-size: 9.5pt; font-family: Consola=
s; color: navy; background-image: initial; background-attachment: initial; =
background-size: initial; background-origin: initial; background-clip: init=
ial; background-position: initial; background-repeat: initial;">v</span><sp=
an style=3D"font-size: 9.5pt; font-family: Consolas; color: black; backgrou=
nd-image: initial; background-attachment: initial; background-size: initial=
; background-origin: initial; background-clip: initial; background-position=
: initial; background-repeat: initial;"> : </span><span style=3D"font-size:=
9.5pt; font-family: Consolas; color: navy; background-image: initial; back=
ground-attachment: initial; background-size: initial; background-origin: in=
itial; background-clip: initial; background-position: initial; background-r=
epeat: initial;">input</span><span style=3D"font-size: 9.5pt; font-family: =
Consolas; color: black; background-image: initial; background-attachment: i=
nitial; background-size: initial; background-origin: initial; background-cl=
ip: initial; background-position: initial; background-repeat: initial;">) <=
o:p></o:p></span></p><p class=3D"MsoNormal" style=3D"margin-top:0in;margin-=
right:0in;margin-bottom:0in;
margin-left:1.0in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-=
align:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: black; background-image: initial; background-attachment: init=
ial; background-size: initial; background-origin: initial; background-clip:=
initial; background-position: initial; background-repeat: initial;">{<o:p>=
</o:p></span></p><p class=3D"MsoNormal" style=3D"margin-top:0in;margin-righ=
t:0in;margin-bottom:0in;
margin-left:1.0in;margin-bottom:.0001pt;text-indent:.5in;line-height:normal=
;
mso-layout-grid-align:none;text-autospace:none"><span style=3D"font-size: 9=
..5pt; font-family: Consolas; color: black; background-image: initial; backg=
round-attachment: initial; background-size: initial; background-origin: ini=
tial; background-clip: initial; background-position: initial; background-re=
peat: initial;">sum +=3D
v;<o:p></o:p></span></p><p class=3D"MsoNormal" style=3D"margin-top:0in;marg=
in-right:0in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;text-indent:.5in;line-height:normal;
mso-layout-grid-align:none;text-autospace:none"><span style=3D"font-size: 9=
..5pt; font-family: Consolas; color: black; background-image: initial; backg=
round-attachment: initial; background-size: initial; background-origin: ini=
tial; background-clip: initial; background-position: initial; background-re=
peat: initial;">}<o:p></o:p></span></p><p class=3D"MsoNormal" style=3D"marg=
in-top:0in;margin-right:0in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-a=
lign:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: black; background-image: initial; background-attachment: init=
ial; background-size: initial; background-origin: initial; background-clip:=
initial; background-position: initial; background-repeat: initial;"> =
</span><span style=3D"font-size: 9.5pt; font=
-family: Consolas; color: blue; background-image: initial; background-attac=
hment: initial; background-size: initial; background-origin: initial; backg=
round-clip: initial; background-position: initial; background-repeat: initi=
al;">return</span><span style=3D"font-size: 9.5pt; font-family: Consolas; c=
olor: black; background-image: initial; background-attachment: initial; bac=
kground-size: initial; background-origin: initial; background-clip: initial=
; background-position: initial; background-repeat: initial;"> sum; <o:p></o=
:p></span></p><p class=3D"MsoNormal" style=3D"margin-top:0in;margin-right:0=
in;margin-bottom:0in;
margin-left:.5in;margin-bottom:.0001pt;line-height:normal;mso-layout-grid-a=
lign:
none;text-autospace:none"><span style=3D"font-size: 9.5pt; font-family: Con=
solas; color: black; background-image: initial; background-attachment: init=
ial; background-size: initial; background-origin: initial; background-clip:=
initial; background-position: initial; background-repeat: initial;">}<o:p>=
</o:p></span></p><p class=3D"MsoNormal"><o:p> </o:p></p><p class=3D"Ms=
oNormal">As a producer:<o:p></o:p></p><p class=3D"Code" style=3D"margin-lef=
t:.5in"><span style=3D"color: rgb(33, 111, 133); background-image: initial;=
background-attachment: initial; background-size: initial; background-origi=
n: initial; background-clip: initial; background-position: initial; backgro=
und-repeat: initial;">async_generator</span><span style=3D"background-image=
: initial; background-attachment: initial; background-size: initial; backgr=
ound-origin: initial; background-clip: initial; background-position: initia=
l; background-repeat: initial;"><<span style=3D"color:blue">int</span>&g=
t; <span style=3D"color:#880000">Ticks</span>() <br>
{<br>
<span style=3D"color:blue">for</span>(=
<span style=3D"color:blue">int</span> tick =3D 0<span style=3D"color:navy">=
;; ++tick) </span></span><span style=3D"text-indent: 0.5in;">{<br></sp=
an><span style=3D"text-indent: 0.5in;"> &=
nbsp;</span><span style=3D"text-indent: 0.5in; color: blue;">yield </span><=
span style=3D"text-indent: 0.5in;">tick;<br></span><span style=3D"text-inde=
nt: 0.5in; background-image: initial; background-attachment: initial; backg=
round-size: initial; background-origin: initial; background-clip: initial; =
background-position: initial; background-repeat: initial;"> &n=
bsp; </span><span style=3D"text-indent: 0.5in; color: b=
lue; background-image: initial; background-attachment: initial; background-=
size: initial; background-origin: initial; background-clip: initial; backgr=
ound-position: initial; background-repeat: initial;">await </span><span sty=
le=3D"text-indent: 0.5in; background-image: initial; background-attachment:=
initial; background-size: initial; background-origin: initial; background-=
clip: initial; background-position: initial; background-repeat: initial;">s=
leep_for(1ms); <br></span><span style=3D"text-indent: 0.=
5in;"> }<br></span><span style=3D"text-indent: 48=
px;">}</span></p><p class=3D"MsoNormal">As a transformer: (adds a timestamp=
to every observed value)<o:p></o:p></p><p class=3D"Code" style=3D"margin-l=
eft:.5in"><span style=3D"color: blue; background-image: initial; background=
-attachment: initial; background-size: initial; background-origin: initial;=
background-clip: initial; background-position: initial; background-repeat:=
initial;">template</span><span style=3D"color: black; background-image: in=
itial; background-attachment: initial; background-size: initial; background=
-origin: initial; background-clip: initial; background-position: initial; b=
ackground-repeat: initial;"><</span><span style=3D"color: blue; backgrou=
nd-image: initial; background-attachment: initial; background-size: initial=
; background-origin: initial; background-clip: initial; background-position=
: initial; background-repeat: initial;">class </span><span style=3D"backgro=
und-image: initial; background-attachment: initial; background-size: initia=
l; background-origin: initial; background-clip: initial; background-positio=
n: initial; background-repeat: initial;">T<span style=3D"color:blue">></=
span><span style=3D"color:black"> </span><br>
async_generator<span style=3D"color:black"><pair<T</span><span style=
=3D"color:blue">,</span> <i>system_clock</i><span style=3D"color:black">::<=
/span><i>time_point</i><span style=3D"color:black">>> <br>
</span><span style=3D"color:#880000">Timestamp</span><span style=3D"color:b=
lack">(</span>async_read_stream<span style=3D"color:black"><T> S) <br=
>
{<br>
</span><span style=3D"color:blue">for
await</span><span style=3D"color:black">(v: S) </span><span style=3D"color:=
blue">yield </span><span style=3D"color:black">{v, </span><i>system_clock</=
i><span style=3D"color:black">::now()};<br></span></span><span style=3D"col=
or: black;">}</span></p><p class=3D"Code" style=3D"margin-left:.5in"><br></=
p><p class=3D"Code" style=3D"margin-left:.5in">Cheers,</p><p class=3D"Code"=
style=3D"margin-left:.5in">Gor</p></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1321_977816604.1414158244755--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Fri, 24 Oct 2014 07:46:40 -0700 (PDT)
Raw View
------=_Part_1862_770612441.1414162000188
Content-Type: text/plain; charset=UTF-8
On Friday, October 24, 2014 2:44:04 PM UTC+1, Gor Nishanov wrote:
>
> Hi Giovanni:
>
>
>> "Same Fringe" requires stackfull coroutines to be implemented efficiently
>> (it needs to yield deep inside a recursive tree visit). With stackless
>> generators (like those of python, C# and those proposed for C++ other than
>> Oliver&Nat proposal), you would need to yield at every stack level but it
>> would in practice make yielding an O(log n) operation,
>>
>
> I don't think so. It depends how you implement yield a generator. In a
> generators, supported by N4134, when you yield not a value but another
> generator, it treats it as await until that generator is finished, thus it
> is always the very top generator that keeps yielding values to the user,
> and when the user pulls the value from the generator it goes straight back
> to the very top one. It does not walk the generator "stack" to do that.
>
Actually right after posting I realized that a sufficiently smart
implementation could do something like that. You would still need to heap
allocate every step of the recursion depth though, right?
>
> Stackful do have cheaper recursive invocations because they have normal
> stack, but it is compensated by more expensive context switch, thus making
> each yield more expensive.
>
> Quick test using boost::context vs N4134 (note we did not implement yet
> any coroutine specific optimizations and our ventual codegen will be much
> better. Remember when Stephanov did STL it was not zero-overhead on any
> existing compiler).
>
> Anyway:
>
> This is what is being tested:
>
> generator<int> GoDeep(int depth) {
> yield depth;
> if (depth > 0) yield GoDeep(depth-1);
> }
>
this is 'tail' recursive though; a full tree visit wouldn't benefit from
it. Does it make a difference with your implementation? Does it allocate a
frame every iteration or the compiler can reuse the frame it was going to
deallocate?
> compared to:
>
[...]
> Stackful: 0.417057 secs: yields 10000000 values 41.705700ns per each
>
> Stackless: 0.517368 secs: yields 10000001 values 51.736836ns per each
>
hum, 41ns per iteration seems a bit high. A stackful coroutine yield should
be around 10 clock cycles: save callee save registers, restore callee save
registers (saving and restoring can be done in parallel), pop return
address and jump (perfectly predictable in this case). In this specific
case even the return is perfectly predicted (which is
> Again, with better codegen we will be beating stackful on recursive
> problems when higher recursive call overhead of stackless is less than
> higher yield cost on stackful.
>
Possibly. Note that also the stackful version could benefit from compiler
support like only saving clobbered registers and saving by moving to unused
registers instead of the stack (which takes advantage of "free" register
renames).
Of course it will always be much easier for the compiler to inline the
callee of a stackless generator than for a stackfull implementation (pretty
much requiring a full CPS conversion).
>
>> frames to support arbitrary recursion depth (in practice reifying the
>> call stack), but I might be wrong here.
>>
>
> Yeah. I really want Chris to chime in, and hopefully provide a full
> implementation for GoDeep()
>
>
Simple extension of an example from N4244
auto countdown_squared(int n)
{
return [n]() resumable
{
std::cout << "Counting down from " << n << "\n";
while (n > 0)
{
yield n;
yield from countdown_squared(n -1);
n -= 1;
}
};
}
As it is, it couldn't possibly compile. countdown_squared will need to wrap
its result in a box.
> Personally I would like to see both styles in the standard: full
>> Oliver&Nat coroutines for the general case and 0-overhead Chris' style
>> generators for iteration
>>
>
> I think stackless can take the coroutine niche. I showed about that
> stackles can match stackful in the problem domain when stackful is king.
>
> However, I do believe that machinery powering N9835 (aka boost::context /
> fibers) is valuable as it can serve as a foundation for cooperative user
> mode threads in C++ / fibers
>
the advantage of the stackful aproaches is that they interoperate with
existing code which is a huge win. No need to convert everything in the
call stack. For example, any function that takes an STL-style output
iterator can be trivially non-intrusively converted to a generator. It has
a cost of course.
>
>> and async continuations that do not require keeping around the full
>> stack. Because of the simplicity I think Chris' work has more chances to
>> get into the standard.
>>
>
> :-) As you can guess, I hold different opinion on this particular point.
>
:) ; As far as I can see N4244 is a strict superset of N4134 (that is,
additional functionality can be built on top), so in the interest of
generality I would prefer the former to the latter.
>
>
>> There is at least another use case for coroutines/generators: Cilk style
>> parent stealing; I think that can also be implemented with 4244, without
>> additional compiler support.
>>
>
> Have you seen parent stealing example from N4134?
>
> spawnable<int> fib(int n) {
> if (n < 2) return n;
> return await(fib(n - 1) + fib(n - 2));
> }
>
I didn't. Very nice. The problem with this is that the obvious
implementation would eagerly convert the parent to a continuation, while an
important optimization of a Cilk style implementation is to lazily perform
the conversion (which includes heap allocating the task and marking the
variables as requiring synchronization) only on a steal. Of course a
Sufficiently Smart Compiler could remove the boxing, but as the
continuation pointer escapes into the (global) work stealing scheduler
itself, I have a feeling it would require an heroic effort unless the
compiler had intimate knowledge of the scheduler.
A N4244 based design would have the parent continuation still reified as an
object, but sitting on the parent stack by default. The stealer would
copy/move it explicitly to the heap/its own stack on a steal.
Anyway, in whatever form, I'm really looking forward to see generators or
coroutines in the standard. Good work guys!
-- gpd
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1862_770612441.1414162000188
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, October 24, 2014 2:44:04 PM UTC+1, Gor Nishanov=
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">Hi Gio=
vanni:<br><div> </div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);bor=
der-left-width:1px;border-left-style:solid"><div dir=3D"ltr">"Same Fringe" =
requires stackfull coroutines to be implemented efficiently (it needs to yi=
eld deep inside a recursive tree visit). With stackless generators (like th=
ose of python, C# and those proposed for C++ other than Oliver&Nat prop=
osal), you would need to yield at every stack level but it would in practic=
e make yielding an O(log n) operation, </div></blockquote><div><br></div><d=
iv>I don't think so. It depends how you implement yield a generator. In a g=
enerators, supported by N4134, when you yield not a value but another gener=
ator, it treats it as await until that generator is finished, thus it is al=
ways the very top generator that keeps yielding values to the user, and whe=
n the user pulls the value from the generator it goes straight back to the =
very top one. It does not walk the generator "stack" to do that.</div></div=
></blockquote><div><br>Actually right after posting I realized that a suffi=
ciently smart implementation could do something like that. You would still =
need to heap allocate every step of the recursion depth though, right?<br>&=
nbsp;</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"><d=
iv><br></div><div>Stackful do have cheaper recursive invocations because th=
ey have normal stack, but it is compensated by more expensive context switc=
h, thus making each yield more expensive.</div><div><br></div><div>Quick te=
st using boost::context vs N4134 (note we did not implement yet any corouti=
ne specific optimizations and our ventual codegen will be much better. Reme=
mber when Stephanov did STL it was not zero-overhead on any existing compil=
er).</div><div><br></div><div>Anyway:</div><div><br></div><div>This is what=
is being tested:</div><div><br></div><div><p><font size=3D"2" face=3D"Cons=
olas">generator<</font><font size=3D"2" face=3D"Consolas" color=3D"#0000=
ff">int</font><font size=3D"2" face=3D"Consolas">> GoDeep(</font><font s=
ize=3D"2" face=3D"Consolas" color=3D"#0000ff">int</font><font size=3D"2" fa=
ce=3D"Consolas"> depth) {<br></font><font style=3D"font-family:Consolas" si=
ze=3D"2" face=3D"Consolas"> </font><font style=3D"font-family:C=
onsolas" face=3D"Consolas" color=3D"#0000ff">yield</font><span style=3D"fon=
t-family:Consolas"> depth;<br></span><font face=3D"Consolas"> <=
/font><font face=3D"Consolas" color=3D"#0000ff">if</font><font face=3D"Cons=
olas"> (depth > 0) </font><font style=3D"font-family:Consolas" face=
=3D"Consolas" color=3D"#0000ff">yield</font><span style=3D"font-family:Cons=
olas"> </span><span style=3D"font-family:Consolas">GoDeep(depth-1);<br=
></span><span style=3D"font-family:Consolas">}</span></p></div></div></bloc=
kquote><div>this is 'tail' recursive though; a full tree visit wouldn't ben=
efit from it. Does it make a difference with your implementation? Does it a=
llocate a frame every iteration or the compiler can reuse the frame it was =
going to deallocate?<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><p><span style=3D"font-family:Consolas">com=
pared to:</span></p></div></div></blockquote><div>[...] <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>Stackful: 0.=
417057 secs: yields 10000000 values 41.705700ns per each<p><span style=3D"f=
ont-family:Consolas">Stackless: 0.517368 secs: yields 10000001 values 51.73=
6836ns per each</span><br></p></div></div></blockquote><div>hum, 41ns per i=
teration seems a bit high. A stackful coroutine yield should be around 10 c=
lock cycles: save callee save registers, restore callee save registers (sav=
ing and restoring can be done in parallel), pop return address and jump (pe=
rfectly predictable in this case). In this specific case even the return is=
perfectly predicted (which is <br> </div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div>Again, with better codegen we will b=
e beating stackful on recursive problems when higher recursive call overhea=
d of stackless is less than higher yield cost on stackful.</div></div></blo=
ckquote><div><br>Possibly. Note that also the stackful version could benefi=
t from compiler support like only saving clobbered registers and saving by =
moving to unused registers instead of the stack (which takes advantage of "=
free" register renames).<br><br>Of course it will always be much easier for=
the compiler to inline the callee of a stackless generator than for a sta=
ckfull implementation (pretty much requiring a full CPS conversion).<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"ltr"><div>&=
nbsp;</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.=
8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1=
px;border-left-style:solid"><div dir=3D"ltr">frames to support arbitrary re=
cursion depth (in practice reifying the call stack), but I might be wrong h=
ere.<br></div></blockquote><div><br></div><div>Yeah. I really want Chris to=
chime in, and hopefully provide a full implementation for GoDeep()</div><d=
iv> </div></div></blockquote><div><br>Simple extension of an example f=
rom N4244<br><br>auto countdown_squared(int n) <br>{ <br>=
return [n]() resumable <br=
> { <br> &=
nbsp; std=
::cout << "Counting down from " << n << "\n"; <br>&=
nbsp; &nbs=
p; while (n > 0) <br> &nb=
sp; =
{ <br> &n=
bsp;  =
; yield n;<br> &=
nbsp; &nbs=
p; yield from countdown_squared(n -1);<br> &nb=
sp; =
n -=3D 1; <br> =
&nb=
sp; } <br> }; <br>}&n=
bsp; <br><br>As it is, it couldn't possibly compile. countdown_squared will=
need to wrap its result in a box.<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"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,20=
4,204);border-left-width:1px;border-left-style:solid"><div dir=3D"ltr">Pers=
onally I would like to see both styles in the standard: full Oliver&Nat=
coroutines for the general case and 0-overhead Chris' style generators for=
iteration </div></blockquote><div><br></div><div>I think stackless can tak=
e the coroutine niche. I showed about that stackles can match stackful in t=
he problem domain when stackful is king.</div><div><br></div><div>However, =
I do believe that machinery powering N9835 (aka boost::context / fibers) is=
valuable as it can serve as a foundation for cooperative user mode threads=
in C++ / fibers</div></div></blockquote><div><br>the advantage of the stac=
kful aproaches is that they interoperate with existing code which is =
a huge win. No need to convert everything in the call stack. For example, a=
ny function that takes an STL-style output iterator can be trivially non-in=
trusively converted to a generator. It has a cost of course.<br><br></div><=
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> </d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padd=
ing-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;borde=
r-left-style:solid"><div dir=3D"ltr">and async continuations that do not re=
quire keeping around the full stack. Because of the simplicity I think Chri=
s' work has more chances to get into the standard.<br></div></blockquote><d=
iv><br></div><div>:-) As you can guess, I hold different opinion on this pa=
rticular point.</div></div></blockquote><div><br> :) ; As far as I can=
see N4244 is a strict superset of N4134 (that is, additional functionality=
can be built on top), so in the interest of generality I would prefer the =
former to the latter.<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><blockquote class=3D"gmail_quote" =
style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(20=
4,204,204);border-left-width:1px;border-left-style:solid"><div dir=3D"ltr">=
There is at least another use case for coroutines/generators: Cilk style pa=
rent stealing; I think that can also be implemented with 4244, without addi=
tional compiler support.<br></div></blockquote><div><br>Have you seen paren=
t stealing example from N4134?</div><div><br></div><p style=3D"margin-left:=
..5in"><span style=3D"background-image:initial;background-repeat:initial">sp=
awnable<<span style=3D"color:blue">int</span>> fib(<span style=3D"col=
or:blue">int</span> n) {<br></span> <span style=
=3D"color:blue">if</span> (n < 2) <span style=3D"color:blue">return</spa=
n>
n;<br> <span style=3D"color:blue">return</span> <=
span style=3D"color:blue">await</span>(fib(n -
1) + fib(n - 2));<br>} </p></div></blockquote><div>I didn't. Very nice=
.. The problem with this is that the obvious implementation would eagerly co=
nvert the parent to a continuation, while an important optimization of a Ci=
lk style implementation is to lazily perform the conversion (which includes=
heap allocating the task and marking the variables as requiring synchroniz=
ation) only on a steal. Of course a Sufficiently Smart Compiler could remov=
e the boxing, but as the continuation pointer escapes into the (global) wor=
k stealing scheduler itself, I have a feeling it would require an heroic ef=
fort unless the compiler had intimate knowledge of the scheduler.<br><br>A =
N4244 based design would have the parent continuation still reified as an o=
bject, but sitting on the parent stack by default. The stealer would copy/m=
ove it explicitly to the heap/its own stack on a steal. <br></div><br=
>Anyway, in whatever form, I'm really looking forward to see generators or =
coroutines in the standard. Good work guys!<br><br>-- gpd<br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1862_770612441.1414162000188--
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Fri, 24 Oct 2014 16:51:36 +0200
Raw View
--089e01229ea85c414105062c517f
Content-Type: text/plain; charset=UTF-8
2014-10-24 16:46 GMT+02:00 Giovanni Piero Deretta <gpderetta@gmail.com>:
> hum, 41ns per iteration seems a bit high. A stackful coroutine yield
> should be around 10 clock cycles: save callee save registers, restore
> callee save registers (saving and restoring can be done in parallel), pop
> return address and jump (perfectly predictable in this case).
>
it depends on the architecture (compare x86_64 SYSV and x86_64 Win64).
maybe Gor missed to enabled optimization and/or to spec.
BOOST_DISABLE_ASSERTS
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e01229ea85c414105062c517f
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">2014=
-10-24 16:46 GMT+02:00 Giovanni Piero Deretta <span dir=3D"ltr"><<a href=
=3D"mailto:gpderetta@gmail.com" target=3D"_blank">gpderetta@gmail.com</a>&g=
t;</span>:<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""></span><div>hum, 41ns per iteration seems a bit high. A stackful coro=
utine yield should be around 10 clock cycles: save callee save registers, r=
estore callee save registers (saving and restoring can be done in parallel)=
, pop return address and jump (perfectly predictable in this case).<br></di=
v></div></blockquote></div><br></div><div class=3D"gmail_extra">it depends =
on the architecture (compare x86_64 SYSV and x86_64 Win64).<br></div><div c=
lass=3D"gmail_extra">maybe Gor missed to enabled optimization and/or to spe=
c. BOOST_DISABLE_ASSERTS<br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01229ea85c414105062c517f--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 24 Oct 2014 08:48:40 -0700 (PDT)
Raw View
------=_Part_1381_183351237.1414165720752
Content-Type: text/plain; charset=UTF-8
On Friday, October 24, 2014 7:51:38 AM UTC-7, Oliver Kowalke wrote:
>
> 2014-10-24 16:46 GMT+02:00 Giovanni Piero Deretta <gpde...@gmail.com
> <javascript:>>:
>
>> hum, 41ns per iteration seems a bit high. A stackful coroutine yield
>> should be around 10 clock cycles: save callee save registers, restore
>> callee save registers (saving and restoring can be done in parallel), pop
>> return address and jump (perfectly predictable in this case).
>>
>
> it depends on the architecture (compare x86_64 SYSV and x86_64 Win64).
> maybe Gor missed to enabled optimization and/or to spec.
> BOOST_DISABLE_ASSERTS
>
This is x86_64 win64. I did not specify as you see in the snippet, I used
default attributes (that save floats).
Adding attributes(flag_fpu_t::fpu_not_preserved) drops it down from:
Stackful: 0.417057 secs: yields 10000000 values 41.705700ns per eac
to
recurse completes in 0.360136 secs: yields 10000001 values 36.013576ns per
each
Though I consider that with modern compilers and CPU not saving floats is
dangerous, unless you disable loop vectorization.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1381_183351237.1414165720752
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><br>On Friday, October 24, 2014 7:51:38 AM UTC-7, Oli=
ver Kowalke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr"><div><div class=3D"gmail_quote">2014-10-24 16:46 GMT+02:00 Giovanni Pi=
ero Deretta <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank"=
gdf-obfuscated-mailto=3D"D-gXZWxJ_9MJ" onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return true;">gpde=
....@gmail.com</a>></span>:<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></span><div>hum, 41ns per iteration seems a bit high. A stackfu=
l coroutine yield should be around 10 clock cycles: save callee save regist=
ers, restore callee save registers (saving and restoring can be done in par=
allel), pop return address and jump (perfectly predictable in this case).<b=
r></div></div></blockquote></div><br></div><div>it depends on the architect=
ure (compare x86_64 SYSV and x86_64 Win64).<br></div><div>maybe Gor missed =
to enabled optimization and/or to spec. BOOST_DISABLE_ASSERTS<br></div></di=
v></blockquote><div><br></div><div>This is x86_64 win64. I did not specify =
as you see in the snippet, I used default attributes (that save floats). Ad=
ding attributes(flag_fpu_t::fpu_not_preserved) drops it down from:</di=
v><div><br></div><div><span style=3D"color: rgb(136, 136, 136);">Stackful:&=
nbsp;0.417057 secs: yields 10000000 values 41.705700ns per eac</span><br></=
div><div><span style=3D"color: rgb(136, 136, 136);">to</span></div><div>rec=
urse completes in 0.360136 secs: yields 10000001 values 36.013576ns per eac=
h</div><div> </div></div><div>Though I consider that with modern compi=
lers and CPU not saving floats is dangerous, unless you disable loop vector=
ization.</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1381_183351237.1414165720752--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Fri, 24 Oct 2014 09:01:15 -0700 (PDT)
Raw View
------=_Part_205_1307785320.1414166475178
Content-Type: text/plain; charset=UTF-8
On Friday, October 24, 2014 4:48:40 PM UTC+1, Gor Nishanov wrote:
>
>
> On Friday, October 24, 2014 7:51:38 AM UTC-7, Oliver Kowalke wrote:
>>
>> 2014-10-24 16:46 GMT+02:00 Giovanni Piero Deretta <gpde...@gmail.com>:
>>
>>> hum, 41ns per iteration seems a bit high. A stackful coroutine yield
>>> should be around 10 clock cycles: save callee save registers, restore
>>> callee save registers (saving and restoring can be done in parallel), pop
>>> return address and jump (perfectly predictable in this case).
>>>
>>
>> it depends on the architecture (compare x86_64 SYSV and x86_64 Win64).
>> maybe Gor missed to enabled optimization and/or to spec.
>> BOOST_DISABLE_ASSERTS
>>
>
> This is x86_64 win64. I did not specify as you see in the snippet, I used
> default attributes (that save floats).
> Adding attributes(flag_fpu_t::fpu_not_preserved) drops it down from:
>
> Stackful: 0.417057 secs: yields 10000000 values 41.705700ns per eac
> to
> recurse completes in 0.360136 secs: yields 10000001 values 36.013576ns per
> each
>
> Though I consider that with modern compilers and CPU not saving floats is
> dangerous, unless you disable loop vectorization.
>
Note that either boost.context or the compiler *will* always preserve float
registers where required by the ABI (I see that on MSVC boost.context
always saves xmm6-15, this is a non-trivial cost which is not required on
some unix abis). The fpu_not_preserved flag only control whether the FPU
control word is preserved. This needs to be done only if the user (or some
library function) explicitly changes it form the default; the compiler may
temporarily change it, but it will also restore it across function calls.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_205_1307785320.1414166475178
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, October 24, 2014 4:48:40 PM UTC+1, Gor Nishanov=
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>On Friday, October 24, 2014 7:51:38 AM UTC-7, Oliver Kowalke wrote:<bloc=
kquote 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"gmai=
l_quote">2014-10-24 16:46 GMT+02:00 Giovanni Piero Deretta <span dir=3D"ltr=
"><<a>gpde...@gmail.com</a>></span>:<br><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><span></span><div>hum, 41ns per iteration seems a bit hi=
gh. A stackful coroutine yield should be around 10 clock cycles: save calle=
e save registers, restore callee save registers (saving and restoring can b=
e done in parallel), pop return address and jump (perfectly predictable in =
this case).<br></div></div></blockquote></div><br></div><div>it depends on =
the architecture (compare x86_64 SYSV and x86_64 Win64).<br></div><div>mayb=
e Gor missed to enabled optimization and/or to spec. BOOST_DISABLE_ASSERTS<=
br></div></div></blockquote><div><br></div><div>This is x86_64 win64. I did=
not specify as you see in the snippet, I used default attributes (that sav=
e floats). Adding attributes(flag_fpu_t::<wbr>fpu_not_preserved) drops=
it down from:</div><div><br></div><div><span style=3D"color:rgb(136,136,13=
6)">Stackful: 0.417057 secs: yields 10000000 values 41.705700ns per ea=
c</span><br></div><div><span style=3D"color:rgb(136,136,136)">to</span></di=
v><div>recurse completes in 0.360136 secs: yields 10000001 values 36.013576=
ns per each</div><div> </div></div><div>Though I consider that with mo=
dern compilers and CPU not saving floats is dangerous, unless you disable l=
oop vectorization.</div></div></blockquote><div><br>Note that either boost.=
context or the compiler *will* always preserve float registers where requir=
ed by the ABI (I see that on MSVC boost.context always saves xmm6-15, this=
is a non-trivial cost which is not required on some unix abis). The fpu_no=
t_preserved flag only control whether the FPU control word is preserved. Th=
is needs to be done only if the user (or some library function) explicitly =
changes it form the default; the compiler may temporarily change it, but it=
will also restore it across function calls.<br> </div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_205_1307785320.1414166475178--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 24 Oct 2014 09:13:39 -0700 (PDT)
Raw View
------=_Part_5_514806934.1414167219617
Content-Type: text/plain; charset=UTF-8
>
> Actually right after posting I realized that a sufficiently smart
> implementation could do something like that. You would still need to heap
> allocate every step of the recursion depth though, right?
>
resursive_generator coroutine type can have an allocator optimized for that
pattern, essentially an allocator will implement chained stack with, chunks
for K size. Reducing the impact of the allocations. Remember, N4134 is just
a language change with appropriate hook ups for library designers go wild.
C++17 will only need 3 coroutine types. generator, task and
async_generator. Moreover, I hope we will keep coroutines in the wild for a
year, before we decide on which generator, which task and which
async_generator. STL did not come together with templates. First you got
templates and min/max. After some number of years, we got an amazing
library utilizing templates.
Of course, coroutines are not as fundamental as templates, but, I do not
want to rush to standardize generators before I can see what smart people
can come up with. I want only the best generator, task and async_generator
selected.
> this is 'tail' recursive though; a full tree visit wouldn't benefit from
> it. Does it make a difference with your implementation? Does it allocate a
> frame every iteration or the compiler can reuse the frame it was going to
> deallocate?
>
This was a torture test. This is the worst case for stackless, Since we
have 1 coroutine frame creation, 1 coroutine frame destruction for every 1
yield. In a real problems where the ration of coroutine creation /
destruction is more favorable, stackless will shine.
Also, yes. on tail recursion. There are a number of coroutine specific
optimizations we are planning and tail yield / await optimization, cross
await RVO and many many others.
> hum, 41ns per iteration seems a bit high. A stackful coroutine yield
> should be around 10 clock cycles: save callee save registers, restore
>
It is dominated by the context switch. On my box defaul context switch is
35ns. Without floats 28ns. This is Windows, it needs to swap more things
than the registers. Exception chain, TLS root, and a few other things.
> Possibly. Note that also the stackful version could benefit from compiler
> support like only saving clobbered registers and saving by moving to unused
> registers instead of the stack (which takes advantage of "free" register
> renames).
>
Oliver and I are exploring that direction. Expect a proposal in the future
if it goes well.
> Simple extension of an example from N4244
>
| ...
> As it is, it couldn't possibly compile. countdown_squared will need to
> wrap its result in a box.
>
Yep. It won't compile. You need to heap allocate the coroutine frame.
I went through it before. My original design was lambda* which is the same
idea as Chris, generalization of lambda with locals / formals and
temporaries of operator() of the lambda included in the lambda state.
I explore it for awhile, but did not find too many cases where I did not
need to wrap the state and place it in some stationary location.
Note, that N4134 allows allocation elision if coroutine lifetime is fully
contained within lifetime of a caller. Thus for generator patterns, some
async patterns, there will no heap allocations whatsoever. Coroutine will
use the frame of its caller.
> call stack. For example, any function that takes an STL-style output
iterator can be trivially non-intrusively converted to a generator. It has
a cost of course.
I only want zero-overhead abstractions in the standard :-).
:) ; As far as I can see N4244 is a strict superset of N4134 (that is,
> additional functionality can be built on top), so in the interest of
> generality I would prefer the former to the latter.
>
I view it as an opposite. N4134 is a syntax sugar on top of unspecified
lambda* and provides friendlier way to adopt it to different patterns.
Makes lambda* concrete. I chose not to expose lambda* directly to have
freedom to do cool optimization and because I did not find a need where
lambda* will be better in perf or convenience than N4134.
If you have a case in mind, please let me know.
My claim is that for any problem solved by N4244, I can solve it with N4134
with simpler code and same or better perf.
I need counter examples, so, Chris, and fans of N4244, please bring me
some. Tear me down! :-)
I didn't. Very nice. The problem with this is that the obvious
> implementation would eagerly convert the parent to a continuation, while an
> important optimization of a Cilk style implementation is to lazily perform
> the conversion (which includes heap allocating the task and marking the
> variables as requiring synchronization) only on a steal.
>
I highly recommend to want this presentation on N4134. I explain the Cilk
example at 23:47. But, of course, I suggest to start from the beginning to
get into the mood :-)
http://www.youtube.com/watch?v=KUhSjfSbINE
Cheers,
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5_514806934.1414167219617
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<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"l=
tr"><div>Actually right after posting I realized that a sufficiently smart =
implementation could do something like that. You would still need to heap a=
llocate every step of the recursion depth though, right?</div></div></block=
quote><div><br></div><div>resursive_generator coroutine type can have an al=
locator optimized for that pattern, essentially an allocator will implement=
chained stack with, chunks for K size. Reducing the impact of the allocati=
ons. Remember, N4134 is just a language change with appropriate hook ups fo=
r library designers go wild.</div><div><br></div><div>C++17 will only need =
3 coroutine types. generator, task and async_generator. Moreover, I hope we=
will keep coroutines in the wild for a year, before we decide on which gen=
erator, which task and which async_generator. STL did not come together wit=
h templates. First you got templates and min/max. After some number of year=
s, we got an amazing library utilizing templates.</div><div><br></div><div>=
Of course, coroutines are not as fundamental as templates, but, I do not wa=
nt to rush to standardize generators before I can see what smart people can=
come up with. I want only the best generator, task and async_generator sel=
ected.</div><div> <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"ltr"><div>this is 'tail' recursive though; a full tree visit=
wouldn't benefit from it. Does it make a difference with your implementati=
on? Does it allocate a frame every iteration or the compiler can reuse the =
frame it was going to deallocate?</div></div></blockquote><div><br></div><d=
iv>This was a torture test. This is the worst case for stackless, Since we =
have 1 coroutine frame creation, 1 coroutine frame destruction for every 1 =
yield. In a real problems where the ration of coroutine creation / destruct=
ion is more favorable, stackless will shine.</div><div><br></div><div>Also,=
yes. on tail recursion. There are a number of coroutine specific optimizat=
ions we are planning and tail yield / await optimization, cross await RVO a=
nd many many others. </div><div> </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>hum, 41ns per iteration seems a bi=
t high. A stackful coroutine yield should be around 10 clock cycles: save c=
allee save registers, restore</div></div></blockquote><div><br></div><div>I=
t is dominated by the context switch. On my box defaul context switch is 35=
ns. Without floats 28ns. This is Windows, it needs to swap more things than=
the registers. Exception chain, TLS root, and a few other things.</div><di=
v> </div><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>Possibly. Note that also the stackful version could benefit from comp=
iler support like only saving clobbered registers and saving by moving to u=
nused registers instead of the stack (which takes advantage of "free" regis=
ter renames).</div></div></blockquote><div><br></div><div>Oliver and I are =
exploring that direction. Expect a proposal in the future if it goes well.&=
nbsp;</div><div> </div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div>Simple extension of an example from N4244<br></div></di=
v></blockquote><div>| ... </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><div>As it is, it couldn't possibly comp=
ile. countdown_squared will need to wrap its result in a box.<br></div></di=
v></blockquote><div><br></div><div>Yep. It won't compile. You need to heap =
allocate the coroutine frame.</div><div><br></div><div>I went through it be=
fore. My original design was lambda* which is the same idea as Chris, gener=
alization of lambda with locals / formals and temporaries of operator() of =
the lambda included in the lambda state.</div><div><br></div><div>I explore=
it for awhile, but did not find too many cases where I did not need to wra=
p the state and place it in some stationary location.</div><div><br></div><=
div>Note, that N4134 allows allocation elision if coroutine lifetime is ful=
ly contained within lifetime of a caller. Thus for generator patterns, some=
async patterns, there will no heap allocations whatsoever. Coroutine will =
use the frame of its caller.</div><div><br></div><div> > call stack=
.. For example, any function that takes an STL-style output iterator can be =
trivially non-intrusively converted to a generator. It has a cost of course=
..</div><div><br></div><div>I only want zero-overhead abstractions in the st=
andard :-).</div><div><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"ltr"><div> :) ; As far as I can see N4244 is a strict su=
perset of N4134 (that is, additional functionality can be built on top), so=
in the interest of generality I would prefer the former to the latter.</di=
v></div></blockquote><div><br></div><div>I view it as an opposite. N4134 is=
a syntax sugar on top of unspecified lambda* and provides friendlier way t=
o adopt it to different patterns.</div><div>Makes lambda* concrete. I chose=
not to expose lambda* directly to have freedom to do cool optimization and=
because I did not find a need where lambda* will be better in perf or conv=
enience than N4134.</div><div><br></div><div>If you have a case in mind, pl=
ease let me know.</div><div><br></div><div>My claim is that for any problem=
solved by N4244, I can solve it with N4134 with simpler code and same or b=
etter perf.</div><div>I need counter examples, so, Chris, and fans of N4244=
, please bring me some. Tear me down! :-)</div><div><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>I didn't. Very nice. =
The problem with this is that the obvious implementation would eagerly conv=
ert the parent to a continuation, while an important optimization of a Cilk=
style implementation is to lazily perform the conversion (which includes h=
eap allocating the task and marking the variables as requiring synchronizat=
ion) only on a steal.</div></div></blockquote><div><br></div><div>I highly =
recommend to want this presentation on N4134. I explain the Cilk example at=
23:47. But, of course, I suggest to start from the beginning to get into t=
he mood :-)</div><div><br></div><div>http://www.youtube.com/watch?v=3DKUhSj=
fSbINE</div><div><br></div><div>Cheers,</div><div>Gor</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5_514806934.1414167219617--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 27 Oct 2014 00:25:31 +0000
Raw View
On Fri, Oct 24, 2014 at 5:13 PM, Gor Nishanov <gornishanov@gmail.com> wrote:
[...]
> Of course, coroutines are not as fundamental as templates, but, I do not
> want to rush to standardize generators before I can see what smart people
> can come up with. I want only the best generator, task and async_generator
> selected.
great :), so give us lambda*, then we will figure out what we can build with it.
[...]
>> hum, 41ns per iteration seems a bit high. A stackful coroutine yield
>> should be around 10 clock cycles: save callee save registers, restore
>
>
> It is dominated by the context switch. On my box defaul context switch is
> 35ns. Without floats 28ns. This is Windows, it needs to swap more things
> than the registers. Exception chain, TLS root, and a few other things.
>
for what is worth, my old 2.4ghz core 2 laptop can do two context
switch in 10ns with my implementation. I could probably do even better
with compiler support (i.e. inline asm and explicit clobber list). On
windows, due an ABI less friendly to this usage, compiler support
could help even more.
[...]
> I went through it before. My original design was lambda* which is the same
> idea as Chris, generalization of lambda with locals / formals and
> temporaries of operator() of the lambda included in the lambda state.
>
> I explore it for awhile, but did not find too many cases where I did not
> need to wrap the state and place it in some stationary location.
>
> Note, that N4134 allows allocation elision if coroutine lifetime is fully
> contained within lifetime of a caller. Thus for generator patterns, some
> async patterns, there will no heap allocations whatsoever. Coroutine will
> use the frame of its caller.
so, will a compiler be able to unbox if I put the generator in an
std::option? boost::variant?
a vector? What if the lifetime of the vector is dynamic? What if I'm
putting the generator in an object which is already heap allocated?
From a custom allocator? In a library that doesn't know about
generators? this is not a far fetched scenario btw: take any existing
async library that takes a callback as a parameter and stores the
callback together with whatever state it needs to carry around.
I mistrust any compiler provided heap elision. First of all, compilers
have always been able to elide visible paired new/delete (as it has
been recently clarified in c++11), still I do not think I have ever
caught my usual compiler doing it in real world code, not even for
standard library types (string, function). Sure, it is nice to have,
but I wouldn't want to rely on it.
Such an optimization relies on escape analysis and thus may or may not
trigger depending on seemingly unrelated code changes. As an example
Java has long promised stack allocation for local objects via escape
analysis, but c#, a similar language, still went with explicit value
type support (and java is considering it), because it is so unreliable
in practice.
Also very often freedom from heap allocation is not just a nice to
have but an absolute requirement, for example when writing lock free
or exception safe code (remember heap allocation can block and can
fail).
Finally, it just doesn't feel right having the compiler allocate
outside of a library facility (the only other language feature,
outside of new of course, that I can think which can potentially
allocate is exception throwing; guess which is the first feature which
is often prohibited in performance critical code?)
It is probably still possible to solve any of the previous issues with
increasingly more complex applications of the allocator hooks, but in
practice if one need to write an allocator for every use case, at some
point it might be simpler to just roll your own hand crafted
generator, at least for performance critical code.
>
> > call stack. For example, any function that takes an STL-style output
> iterator can be trivially non-intrusively converted to a generator. It has a
> cost of course.
>
> I only want zero-overhead abstractions in the standard :-).
>
so why are you proposing generators that are boxed by default ? :)
>> :) ; As far as I can see N4244 is a strict superset of N4134 (that is,
>> additional functionality can be built on top), so in the interest of
>> generality I would prefer the former to the latter.
>
>
> I view it as an opposite. N4134 is a syntax sugar on top of unspecified
> lambda* and provides friendlier way to adopt it to different patterns.
> Makes lambda* concrete. I chose not to expose lambda* directly to have
> freedom to do cool optimization and because I did not find a need where
> lambda* will be better in perf or convenience than N4134.
>
> If you have a case in mind, please let me know.
>
> My claim is that for any problem solved by N4244, I can solve it with N4134
> with simpler code and same or better perf.
> I need counter examples, so, Chris, and fans of N4244, please bring me some.
> Tear me down! :-)
can I easily (note: simpler code) put an N4134 in a
boost::multiprocess container and serialize it? (why would i want to
do it? persistent continuation based servers are a cool thing).
can I copy it? N4134 doesn't say whether a generator is a regular type
at all (it seems to be hinted in the appendinx when showing the
iterator, but it is not clear). Why would I want to copy it?
Multi-pass iteration, backtracking, etc. .
Really those two were just two things of the top of my head. Simple
stack allocated regular types are the strength of c++, we know how to
(ab)use them; it worked exceptionally well for lambda, let's do more
of them!
>
>> I didn't. Very nice. The problem with this is that the obvious
>> implementation would eagerly convert the parent to a continuation, while an
>> important optimization of a Cilk style implementation is to lazily perform
>> the conversion (which includes heap allocating the task and marking the
>> variables as requiring synchronization) only on a steal.
>
>
> I highly recommend to want this presentation on N4134. I explain the Cilk
> example at 23:47. But, of course, I suggest to start from the beginning to
> get into the mood :-)
>
I will eventually, but I find videos a very inefficient way to
transmit information :(.
Anyways, at 23.47 really not much more than the stealing example
itself is presented. The implementation and in particular the
optimization I mentioned above is not discussed.
-- gpd
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Mon, 27 Oct 2014 15:28:02 +0700
Raw View
--001a113d6bfe4f756a0506635077
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> I mistrust any compiler provided heap elision.
I completely agree on this. Why rely on QoI when we can just use function
objects?
This is the part that makes me more concerned about n4134, IF I understood
the proposal.
To me it seems that a function object interface has benefits. It is
lightweight by itself and really
easy to reason about.
> at some
> point it might be simpler to just roll your own hand crafted
> generator, at least for performance critical code.
I am commenting on another thread on this as well: allocator hooks. Why not
to eliminate the need for heap
allocs by default, in the first place? Would make use simpler from
coroutine user POV. I see as potentially dangerous
a language feature that relies on heap allocation without informing the
user.
One of the things I like about C++ is that I have complete control about
what happens with memory when I write simple
code such as stack variables that are part of the language itself.
> can I copy it? N4134 doesn't say whether a generator is a regular type
> at all (it seems to be hinted in the appendinx when showing the
> iterator, but it is not clear). Why would I want to copy it?
> Multi-pass iteration, backtracking, etc.
I find N4244 abstraction easier to understand and reason about as well.
Couldn't we have an abstraction that is more "transparent" than N4134.
To me N4134 looks more like a "framework" for coroutines, N4244 seems to be
more like: this is a coroutine and
it is all that you need -> a function object.
I cannot agree more with your concerns, since they seem to match mine in
the thread "Question for Germ=C3=A1n Diago..."
Regards,
Germ=C3=A1n Diago G=C3=B3mez
2014-10-27 7:25 GMT+07:00 Giovanni Piero Deretta <gpderetta@gmail.com>:
> On Fri, Oct 24, 2014 at 5:13 PM, Gor Nishanov <gornishanov@gmail.com>
> wrote:
> [...]
> > Of course, coroutines are not as fundamental as templates, but, I do no=
t
> > want to rush to standardize generators before I can see what smart peop=
le
> > can come up with. I want only the best generator, task and
> async_generator
> > selected.
>
> great :), so give us lambda*, then we will figure out what we can build
> with it.
>
> [...]
> >> hum, 41ns per iteration seems a bit high. A stackful coroutine yield
> >> should be around 10 clock cycles: save callee save registers, restore
> >
> >
> > It is dominated by the context switch. On my box defaul context switch =
is
> > 35ns. Without floats 28ns. This is Windows, it needs to swap more thing=
s
> > than the registers. Exception chain, TLS root, and a few other things.
> >
>
> for what is worth, my old 2.4ghz core 2 laptop can do two context
> switch in 10ns with my implementation. I could probably do even better
> with compiler support (i.e. inline asm and explicit clobber list). On
> windows, due an ABI less friendly to this usage, compiler support
> could help even more.
>
> [...]
> > I went through it before. My original design was lambda* which is the
> same
> > idea as Chris, generalization of lambda with locals / formals and
> > temporaries of operator() of the lambda included in the lambda state.
> >
> > I explore it for awhile, but did not find too many cases where I did no=
t
> > need to wrap the state and place it in some stationary location.
> >
> > Note, that N4134 allows allocation elision if coroutine lifetime is ful=
ly
> > contained within lifetime of a caller. Thus for generator patterns, som=
e
> > async patterns, there will no heap allocations whatsoever. Coroutine wi=
ll
> > use the frame of its caller.
>
> so, will a compiler be able to unbox if I put the generator in an
> std::option? boost::variant?
> a vector? What if the lifetime of the vector is dynamic? What if I'm
> putting the generator in an object which is already heap allocated?
> From a custom allocator? In a library that doesn't know about
> generators? this is not a far fetched scenario btw: take any existing
> async library that takes a callback as a parameter and stores the
> callback together with whatever state it needs to carry around.
>
> I mistrust any compiler provided heap elision. First of all, compilers
> have always been able to elide visible paired new/delete (as it has
> been recently clarified in c++11), still I do not think I have ever
> caught my usual compiler doing it in real world code, not even for
> standard library types (string, function). Sure, it is nice to have,
> but I wouldn't want to rely on it.
>
> Such an optimization relies on escape analysis and thus may or may not
> trigger depending on seemingly unrelated code changes. As an example
> Java has long promised stack allocation for local objects via escape
> analysis, but c#, a similar language, still went with explicit value
> type support (and java is considering it), because it is so unreliable
> in practice.
>
> Also very often freedom from heap allocation is not just a nice to
> have but an absolute requirement, for example when writing lock free
> or exception safe code (remember heap allocation can block and can
> fail).
>
> Finally, it just doesn't feel right having the compiler allocate
> outside of a library facility (the only other language feature,
> outside of new of course, that I can think which can potentially
> allocate is exception throwing; guess which is the first feature which
> is often prohibited in performance critical code?)
>
> It is probably still possible to solve any of the previous issues with
> increasingly more complex applications of the allocator hooks, but in
> practice if one need to write an allocator for every use case, at some
> point it might be simpler to just roll your own hand crafted
> generator, at least for performance critical code.
>
>
> >
> > > call stack. For example, any function that takes an STL-style output
> > iterator can be trivially non-intrusively converted to a generator. It
> has a
> > cost of course.
> >
> > I only want zero-overhead abstractions in the standard :-).
> >
>
> so why are you proposing generators that are boxed by default ? :)
>
> >> :) ; As far as I can see N4244 is a strict superset of N4134 (that is=
,
> >> additional functionality can be built on top), so in the interest of
> >> generality I would prefer the former to the latter.
> >
> >
> > I view it as an opposite. N4134 is a syntax sugar on top of unspecified
> > lambda* and provides friendlier way to adopt it to different patterns.
> > Makes lambda* concrete. I chose not to expose lambda* directly to have
> > freedom to do cool optimization and because I did not find a need where
> > lambda* will be better in perf or convenience than N4134.
> >
> > If you have a case in mind, please let me know.
> >
> > My claim is that for any problem solved by N4244, I can solve it with
> N4134
> > with simpler code and same or better perf.
> > I need counter examples, so, Chris, and fans of N4244, please bring me
> some.
> > Tear me down! :-)
>
> can I easily (note: simpler code) put an N4134 in a
> boost::multiprocess container and serialize it? (why would i want to
> do it? persistent continuation based servers are a cool thing).
>
> can I copy it? N4134 doesn't say whether a generator is a regular type
> at all (it seems to be hinted in the appendinx when showing the
> iterator, but it is not clear). Why would I want to copy it?
> Multi-pass iteration, backtracking, etc. .
>
> Really those two were just two things of the top of my head. Simple
> stack allocated regular types are the strength of c++, we know how to
> (ab)use them; it worked exceptionally well for lambda, let's do more
> of them!
>
> >
> >> I didn't. Very nice. The problem with this is that the obvious
> >> implementation would eagerly convert the parent to a continuation,
> while an
> >> important optimization of a Cilk style implementation is to lazily
> perform
> >> the conversion (which includes heap allocating the task and marking th=
e
> >> variables as requiring synchronization) only on a steal.
> >
> >
> > I highly recommend to want this presentation on N4134. I explain the Ci=
lk
> > example at 23:47. But, of course, I suggest to start from the beginning
> to
> > get into the mood :-)
> >
>
> I will eventually, but I find videos a very inefficient way to
> transmit information :(.
> Anyways, at 23.47 really not much more than the stealing example
> itself is presented. The implementation and in particular the
> optimization I mentioned above is not discussed.
>
> -- gpd
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a113d6bfe4f756a0506635077
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><span style=3D"font-family:arial,sans-serif;font-size:13px=
">> I mistrust any compiler provided heap elision.=C2=A0</span><br><div>=
<span style=3D"font-family:arial,sans-serif;font-size:13px"><br></span></di=
v><div><span style=3D"font-family:arial,sans-serif;font-size:13px">I comple=
tely agree on this. Why rely on QoI when we can just use function objects?<=
/span></div><div><span style=3D"font-family:arial,sans-serif;font-size:13px=
">This is the part that makes me more concerned about n4134, IF I understoo=
d the proposal.</span></div><div><span style=3D"font-family:arial,sans-seri=
f;font-size:13px"><br></span></div><div><span style=3D"font-family:arial,sa=
ns-serif;font-size:13px">To me it seems that a function object interface ha=
s benefits. It is lightweight by itself and really</span></div><div><span s=
tyle=3D"font-family:arial,sans-serif;font-size:13px">easy to reason about.<=
/span></div><div><span style=3D"font-family:arial,sans-serif;font-size:13px=
"><br></span></div><div><span style=3D"font-family:arial,sans-serif;font-si=
ze:13px">> at some</span><br style=3D"font-family:arial,sans-serif;font-=
size:13px"><span style=3D"font-family:arial,sans-serif;font-size:13px">>=
point it might be simpler to just roll your own hand crafted</span><br sty=
le=3D"font-family:arial,sans-serif;font-size:13px"><span style=3D"font-fami=
ly:arial,sans-serif;font-size:13px">> generator, at least for performanc=
e critical code.</span><span style=3D"font-family:arial,sans-serif;font-siz=
e:13px"><br></span></div><div><span style=3D"font-family:arial,sans-serif;f=
ont-size:13px"><br></span></div><div><span style=3D"font-family:arial,sans-=
serif;font-size:13px">I am commenting on another thread on this as well: al=
locator hooks. Why not to eliminate the need for heap</span></div><div><spa=
n style=3D"font-family:arial,sans-serif;font-size:13px">allocs=C2=A0</span>=
<span style=3D"font-family:arial,sans-serif;font-size:13px">by default, in =
the first place? Would make use simpler from coroutine user POV. I see as p=
otentially dangerous</span></div><div><span style=3D"font-family:arial,sans=
-serif;font-size:13px">a language feature that relies on heap allocation wi=
thout informing the user.</span></div><div><span style=3D"font-family:arial=
,sans-serif;font-size:13px">One of the things I like about C++ is that I ha=
ve complete control about what happens with memory when I write simple</spa=
n></div><div><span style=3D"font-family:arial,sans-serif;font-size:13px">co=
de such as stack variables that are part of the language itself.</span></di=
v><div><span style=3D"font-family:arial,sans-serif;font-size:13px"><br></sp=
an></div><div><span style=3D"font-family:arial,sans-serif;font-size:13px">&=
gt; can I copy it? N4134 doesn't say whether a generator is a regular t=
ype</span><br style=3D"font-family:arial,sans-serif;font-size:13px"><span s=
tyle=3D"font-family:arial,sans-serif;font-size:13px">> at all (it seems =
to be hinted in the appendinx when showing the</span><br style=3D"font-fami=
ly:arial,sans-serif;font-size:13px"><span style=3D"font-family:arial,sans-s=
erif;font-size:13px">> iterator, but it is not clear). Why would I want =
to copy it?</span><br style=3D"font-family:arial,sans-serif;font-size:13px"=
><span style=3D"font-family:arial,sans-serif;font-size:13px">> Multi-pas=
s iteration, backtracking, etc.</span></div><div><span style=3D"font-family=
:arial,sans-serif;font-size:13px"><br></span></div><div><span style=3D"font=
-family:arial,sans-serif;font-size:13px">I find N4244 abstraction easier to=
understand and reason about as well.=C2=A0</span></div><div><span style=3D=
"font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span s=
tyle=3D"font-family:arial,sans-serif;font-size:13px">Couldn't we have a=
n abstraction that is more "transparent" than N4134.</span></div>=
<div><span style=3D"font-family:arial,sans-serif;font-size:13px">To me N413=
4 looks more like a "framework" for coroutines, N4244 seems to be=
more like: this is a coroutine and</span></div><div><span style=3D"font-fa=
mily:arial,sans-serif;font-size:13px">it is all that you need -> a funct=
ion object.=C2=A0</span></div><div><span style=3D"font-family:arial,sans-se=
rif;font-size:13px"><br></span></div><div><span style=3D"font-family:arial,=
sans-serif;font-size:13px">I cannot agree more with your concerns, since th=
ey seem to match mine in the thread "Question for Germ=C3=A1n Diago...=
"</span></div><div><span style=3D"font-family:arial,sans-serif;font-si=
ze:13px"><br></span></div><div><span style=3D"font-family:arial,sans-serif;=
font-size:13px">Regards,</span></div><div><span style=3D"font-family:arial,=
sans-serif;font-size:13px">Germ=C3=A1n Diago G=C3=B3mez</span></div></div><=
div class=3D"gmail_extra"><br><div class=3D"gmail_quote">2014-10-27 7:25 GM=
T+07:00 Giovanni Piero Deretta <span dir=3D"ltr"><<a href=3D"mailto:gpde=
retta@gmail.com" target=3D"_blank">gpderetta@gmail.com</a>></span>:<br><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex">On Fri, Oct 24, 2014 at 5:13 PM, Gor Nishanov=
<<a href=3D"mailto:gornishanov@gmail.com">gornishanov@gmail.com</a>>=
wrote:<br>
[...]<br>
<span class=3D"">> Of course, coroutines are not as fundamental as templ=
ates, but, I do not<br>
> want to rush to standardize generators before I can see what smart peo=
ple<br>
> can come up with. I want only the best generator, task and async_gener=
ator<br>
> selected.<br>
<br>
</span>great :), so give us lambda*, then we will figure out what we can bu=
ild with it.<br>
<br>
[...]<br>
<span class=3D"">>> hum, 41ns per iteration seems a bit high. A stack=
ful coroutine yield<br>
>> should be around 10 clock cycles: save callee save registers, rest=
ore<br>
><br>
><br>
> It is dominated by the context switch. On my box defaul context switch=
is<br>
> 35ns. Without floats 28ns. This is Windows, it needs to swap more thin=
gs<br>
> than the registers. Exception chain, TLS root, and a few other things.=
<br>
><br>
<br>
</span>for what is worth, my old 2.4ghz core 2 laptop can do two context<br=
>
switch in 10ns with my implementation. I could probably do even better<br>
with compiler support (i.e. inline asm and explicit clobber list). On<br>
windows, due an ABI less friendly to this usage, compiler support<br>
could help even more.<br>
<br>
[...]<br>
<span class=3D"">> I went through it before. My original design was lamb=
da* which is the same<br>
> idea as Chris, generalization of lambda with locals / formals and<br>
> temporaries of operator() of the lambda included in the lambda state.<=
br>
><br>
> I explore it for awhile, but did not find too many cases where I did n=
ot<br>
> need to wrap the state and place it in some stationary location.<br>
><br>
> Note, that N4134 allows allocation elision if coroutine lifetime is fu=
lly<br>
> contained within lifetime of a caller. Thus for generator patterns, so=
me<br>
> async patterns, there will no heap allocations whatsoever. Coroutine w=
ill<br>
> use the frame of its caller.<br>
<br>
</span>so, will a compiler be able to unbox if I put the generator in an<br=
>
std::option? boost::variant?<br>
a vector? What if the lifetime of the vector is dynamic? What if I'm<br=
>
putting the generator in an object which is already heap allocated?<br>
From a custom allocator? In a library that doesn't know about<br>
generators? this is not a far fetched scenario btw: take any existing<br>
async library that takes a callback as a parameter and stores the<br>
callback together with whatever state it needs to carry around.<br>
<br>
I mistrust any compiler provided heap elision. First of all, compilers<br>
have always been able to elide visible paired new/delete=C2=A0 (as it has<b=
r>
been recently clarified in c++11), still I do not think I have ever<br>
caught my usual=C2=A0 compiler doing it in real world code, not even for<br=
>
standard library types (string, function). Sure, it is nice to have,<br>
but I wouldn't want to rely on it.<br>
<br>
Such an optimization relies on escape analysis and thus may or may not<br>
trigger depending on seemingly unrelated code changes. As an example<br>
Java has long promised stack allocation for local objects via escape<br>
analysis, but c#, a similar language, still went with explicit value<br>
type support (and java is considering it), because it is so unreliable<br>
in practice.<br>
<br>
Also very often freedom from heap allocation is not just a nice to<br>
have but an absolute requirement, for example when writing lock free<br>
or exception safe code (remember heap allocation can block and can<br>
fail).<br>
<br>
Finally, it just doesn't feel right having the compiler allocate<br>
outside of a library facility (the only other language feature,<br>
outside of new of course, that I can think which can potentially<br>
allocate is exception throwing; guess which is the first feature which<br>
is often prohibited in performance critical code?)<br>
<br>
It is probably still possible to solve any of the previous issues with<br>
increasingly more complex applications of the allocator hooks, but in<br>
practice if one need to write an allocator for every use case, at some<br>
point it might be simpler to just roll your own hand crafted<br>
generator, at least for performance critical code.<br>
<span class=3D""><br>
<br>
><br>
>=C2=A0 > call stack. For example, any function that takes an STL-sty=
le output<br>
> iterator can be trivially non-intrusively converted to a generator. It=
has a<br>
> cost of course.<br>
><br>
> I only want zero-overhead abstractions in the standard :-).<br>
><br>
<br>
</span>so why are you proposing generators that are boxed by default ? :)<b=
r>
<span class=3D""><br>
>>=C2=A0 :) ; As far as I can see N4244 is a strict superset of N4134=
(that is,<br>
>> additional functionality can be built on top), so in the interest =
of<br>
>> generality I would prefer the former to the latter.<br>
><br>
><br>
> I view it as an opposite. N4134 is a syntax sugar on top of unspecifie=
d<br>
> lambda* and provides friendlier way to adopt it to different patterns.=
<br>
> Makes lambda* concrete. I chose not to expose lambda* directly to have=
<br>
> freedom to do cool optimization and because I did not find a need wher=
e<br>
> lambda* will be better in perf or convenience than N4134.<br>
><br>
> If you have a case in mind, please let me know.<br>
><br>
> My claim is that for any problem solved by N4244, I can solve it with =
N4134<br>
> with simpler code and same or better perf.<br>
> I need counter examples, so, Chris, and fans of N4244, please bring me=
some.<br>
> Tear me down! :-)<br>
<br>
</span>can I easily (note: simpler code) put an N4134 in a<br>
boost::multiprocess container and serialize it? (why would i want to<br>
do it? persistent continuation based servers are a cool thing).<br>
<br>
can I copy it? N4134 doesn't say whether a generator is a regular type<=
br>
at all (it seems to be hinted in the appendinx when showing the<br>
iterator, but it is not clear). Why would I want to copy it?<br>
Multi-pass iteration, backtracking, etc. .<br>
<br>
Really those two were just two things of the top of my head. Simple<br>
stack allocated regular types are the strength of c++, we know how to<br>
(ab)use them; it worked exceptionally well for lambda, let's do more<br=
>
of them!<br>
<span class=3D""><br>
><br>
>> I didn't. Very nice. The problem with this is that the obvious=
<br>
>> implementation would eagerly convert the parent to a continuation,=
while an<br>
>> important optimization of a Cilk style implementation is to lazily=
perform<br>
>> the conversion (which includes heap allocating the task and markin=
g the<br>
>> variables as requiring synchronization) only on a steal.<br>
><br>
><br>
> I highly recommend to want this presentation on N4134. I explain the C=
ilk<br>
> example at 23:47. But, of course, I suggest to start from the beginnin=
g to<br>
> get into the mood :-)<br>
><br>
<br>
</span>I will eventually, but I find videos a very inefficient way to<br>
transmit information :(.<br>
Anyways, at 23.47 really not much more than the stealing example<br>
itself is presented. The implementation and in particular the<br>
optimization I mentioned above is not discussed.<br>
<span class=3D"HOEnZb"><font color=3D"#888888"><br>
-- gpd<br>
</font></span><div class=3D"HOEnZb"><div class=3D"h5"><br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113d6bfe4f756a0506635077--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 27 Oct 2014 03:38:11 -0700 (PDT)
Raw View
------=_Part_160_2069338374.1414406291300
Content-Type: text/plain; charset=UTF-8
[ One last thing, then I promise I'll shut up. As you can tell I fell
pretty strongly about this :) ]
On Monday, October 27, 2014 12:25:32 AM UTC, Giovanni Piero Deretta wrote:
[...]
Simple stack allocated regular types are the strength of c++, we know how
to
> (ab)use them; it worked exceptionally well for lambda, let's do more
> of them!
>
>
To expand of this point, lambda make a perfect example of why generators
should also be "naked". Most languages before and after C++ heap allocate
their closure and rely on compiler optimizations to remove the abstraction.
It has worked very well in many languages (even the Objective C dialect of
C heap allocates its closures!), but still C++ went with stack allocated
one-type-per-closure lambdas, with explicit boxing (we call it
std::function) when required.
Could have C++ gone with boxing by default and rely on compiler
optimization to remove the overhead? Possibly, but consider another data
point: the Rust language is in the same domain as C++ (literally: it is
being explicitly designed as a replacement) and as such offers the same
object model: manual (but still memory safe) memory management, no implicit
heap allocations, value types as default, parametric polymorphism via
monomorphization, zero cost abstractions, etc. Still, as the developers
came from a functional background (ML), they decided to box their closures
[1], as it is just the way it is normally done; as their backend is based
on LLVM which has explicit mature optimization passes to remove matched
heap allocation/deallocation and indirect calls they felt the compiler
would be able to remove the abstractions in all interesting cases.
Fast forward a few years later, in both benchmarks and real code which use
higher order functions (which in Rust is pretty much everything, including
'for' loops), Rust has troubles matching the performance of c++ because of
of boxed closures. Now the developers are in the process of ripping them
out and replacing them with unboxed, uniquely typed closures (with pretty
much the same semantics of C++ lambdas, including explicit capture lists).
HTH,
-- gpd
[1] as far as I understand closures which are bound to an automatic scope
are not actually heap allocated, but they are still boxed, i.e. type erased
and behind a indirect call.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_160_2069338374.1414406291300
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">[ One last thing, then I promise I'll shut up. As you can =
tell I fell pretty strongly about this :) ]<br><br>On Monday, October 27, 2=
014 12:25:32 AM UTC, Giovanni Piero Deretta wrote:<br>[...] <div> Simp=
le
stack allocated regular types are the strength of c++, we know how to
<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">(ab)use them; it wor=
ked exceptionally well for lambda, let's do more
<br>of them!
<br>
<br></blockquote><div><br>To expand of this point, lambda make a perfect ex=
ample of why generators should also be "naked". Most languages before and a=
fter C++ heap allocate their closure and rely on compiler optimizations to =
remove the abstraction. It has worked very well in many languages (even the=
Objective C dialect of C heap allocates its closures!), but still C++ went=
with stack allocated one-type-per-closure lambdas, with explicit boxing (w=
e call it std::function) when required. <br><br>Could have C++ gone with bo=
xing by default and rely on compiler optimization to remove the overhead? P=
ossibly, but consider another data point: the Rust language is in the same =
domain as C++ (literally: it is being explicitly designed as a replacement)=
and as such offers the same object model: manual (but still memory safe) m=
emory management, no implicit heap allocations, value types as default, par=
ametric polymorphism via monomorphization, zero cost abstractions, etc. Sti=
ll, as the developers came from a functional background (ML), they decided =
to box their closures [1], as it is just the way it is normally done; as th=
eir backend is based on LLVM which has explicit mature optimization passes =
to remove matched heap allocation/deallocation and indirect calls the=
y felt the compiler would be able to remove the abstractions in all interes=
ting cases. <br><br>Fast forward a few years later, in both benchmarks and =
real code which use higher order functions (which in Rust is pretty much ev=
erything, including 'for' loops), Rust has troubles matching the performanc=
e of c++ because of of boxed closures. Now the developers are in the proces=
s of ripping them out and replacing them with unboxed, uniquely typed closu=
res (with pretty much the same semantics of C++ lambdas, including explicit=
capture lists).<br><br>HTH,<br><br>-- gpd<br> <br>[1] as far as I und=
erstand closures which are bound to an automatic scope are not actually hea=
p allocated, but they are still boxed, i.e. type erased and behind a indire=
ct call.<br><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_160_2069338374.1414406291300--
.
Author: german.gomez@personifyinc.com
Date: Mon, 27 Oct 2014 04:14:51 -0700 (PDT)
Raw View
------=_Part_269_1323241347.1414408491790
Content-Type: text/plain; charset=UTF-8
On Monday, October 27, 2014 5:38:11 PM UTC+7, Giovanni Piero Deretta wrote:
>
>
> Fast forward a few years later, in both benchmarks and real code which use
> higher order functions (which in Rust is pretty much everything, including
> 'for' loops), Rust has troubles matching the performance of c++ because of
> of boxed closures. Now the developers are in the process of ripping them
> out and replacing them with unboxed, uniquely typed closures (with pretty
> much the same semantics of C++ lambdas, including explicit capture lists).
>
>
> -- gpd
>
> [1] as far as I understand closures which are bound to an automatic scope
> are not actually heap allocated, but they are still boxed, i.e. type erased
> and behind a indirect call.
>
The more I hear, the more I favour n4244 function object approach. It is
the ONLY way to have a guaranteed zero overhead abstraction.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_269_1323241347.1414408491790
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, October 27, 2014 5:38:11 PM UTC+7, Giov=
anni Piero Deretta 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>Fast forward a few years later, in both benchmarks and=
real code which use higher order functions (which in Rust is pretty much e=
verything, including 'for' loops), Rust has troubles matching the performan=
ce of c++ because of of boxed closures. Now the developers are in the proce=
ss of ripping them out and replacing them with unboxed, uniquely typed clos=
ures (with pretty much the same semantics of C++ lambdas, including explici=
t capture lists).<br><br><br>-- gpd<br> <br>[1] as far as I understand=
closures which are bound to an automatic scope are not actually heap alloc=
ated, but they are still boxed, i.e. type erased and behind a indirect call=
..<br></div></div></blockquote><div><br></div><div>The more I hear, the more=
I favour n4244 function object approach. It is the ONLY way to have a guar=
anteed zero overhead abstraction.</div><div><br></div><div><br></div><div>&=
nbsp;</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_269_1323241347.1414408491790--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 27 Oct 2014 17:47:53 -0700 (PDT)
Raw View
------=_Part_2276_1310152631.1414457273106
Content-Type: text/plain; charset=UTF-8
>
> great :), so give us lambda*, then we will figure out what we can build
> with it.
>
Having N4134 does not preclude exposing lambda* later if there are use
cases for it and unsolved yet issues with lambda* / N4244 are resolved.
(Page 6 last paragraph)
> [...] windows, due an ABI less friendly to this usage, compiler support
> could help even more.
>
I am not sure how compiler can help. Oliver's assembly routines are as fast
as you can get for stackful context switch:
*https://github.com/Beman/boost-trunk-git-svn/blob/master/libs/context/src/asm/jump_x86_64_ms_pe_masm.asm*
<https://github.com/Beman/boost-trunk-git-svn/blob/master/libs/context/src/asm/jump_x86_64_ms_pe_masm.asm>
> so, will a compiler be able to unbox if I put the generator in an
> std::option? boost::variant?
>
If there is no suspension needed, such as with optional, there is no
coroutine frame at all.
It is a normal function in all aspects. No need for allocation elision at
all.
> caught my usual compiler doing it in real world code, not even for
> standard library types (string, function). Sure, it is nice to have,
>
Well, Microsoft compiler will do it. Other compiler better catch up :-) .
> type support (and java is considering it), because it is so unreliable
> in practice.
>
This is targeted optimization specific to coroutines. We do not reply on
general purpose malloc/free elisions.
We put a wording in the N4134 about it on purpose, so that we are free to
do it.
Whether allocator is called or not is observable, and thus do not fall
under "as if" rule
Finally, it just doesn't feel right having the compiler allocate
> outside of a library facility (the only other language feature,
>
Considered is to be similar to a new. Compiler does calls a library
facility to do an allocation and then constructs the object.
Very similar in this case.
> allocate is exception throwing; guess which is the first feature which
> is often prohibited in performance critical code?)
>
Hence a section in N4134 about using coroutines in the environments where
exceptions are not available or banned.
> so why are you proposing generators that are boxed by default ? :)
>
STL was not a zero overhead library in C++98.
It is now. Compilers caught up.
Luckily I am on a compiler team and I am a fan of coroutines. I think I can
influence a little bit our compiler to do the right job. :-)
> Multi-pass iteration, backtracking, etc. .
>
This actions are not safe in a general case, hence I am not proposing them
now.
If there is enough people pushing for them, it can be easily added later.
One way to extend N4134 to allow that is to extend
resumable_handle (probably will rename it to coroutine_handle) to add
coroutine_handle::clone() that clones the coroutine
coroutine_handle::save(buf)
coroutine_handle::revive(buf)
or something like that. Then library writer can use them to do whatever
they think is needed.
Cheers,
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2276_1310152631.1414457273106
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;">great :), so give us lambda*,=
then we will figure out what we can build with it.
<br></blockquote><div><br></div><div>Having N4134 does not preclude exposin=
g lambda* later if there are use cases for it and unsolved yet issues with =
lambda* / N4244 are resolved. (Page 6 last paragraph)</div><div><br></div><=
div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border=
-left-width: 1px; border-left-style: solid;">[...]
windows, due an ABI less friendly to this usage, compiler support
<br>could help even more.
<br></blockquote><div><br></div><div>I am not sure how compiler can help. O=
liver's assembly routines are as fast as you can get for stackful context s=
witch: <span style=3D'color: rgb(31, 73, 125); font-family: "Calibri","sans=
-serif"; font-size: 11pt; mso-fareast-font-family: Calibri; mso-fareast-the=
me-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-ansi-lan=
guage: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA;'><a hr=
ef=3D"https://github.com/Beman/boost-trunk-git-svn/blob/master/libs/context=
/src/asm/jump_x86_64_ms_pe_masm.asm"><u><font color=3D"#0000ff">https://git=
hub.com/Beman/boost-trunk-git-svn/blob/master/libs/context/src/asm/jump_x86=
_64_ms_pe_masm.asm</font></u></a></span></div><div><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; =
border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-=
style: solid;"><br>so, will a compiler be able to unbox if I put the genera=
tor in an
<br>std::option? boost::variant?
<br></blockquote><div><br></div><div>If there is no suspension needed, such=
as with optional, there is no coroutine frame at all.</div><div>It is a no=
rmal function in all aspects. No need for allocation elision at all.</div><=
div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border=
-left-width: 1px; border-left-style: solid;">caught my usual compiler=
doing it in real world code, not even for
<br>standard library types (string, function). Sure, it is nice to have,
<br></blockquote><div><br></div><div>Well, Microsoft compiler will do it. O=
ther compiler better catch up :-) .</div><div> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; bor=
der-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-sty=
le: solid;">type support (and java is considering it), because it is so unr=
eliable
<br>in practice.
<br></blockquote><div><br></div><div>This is targeted optimization spe=
cific to coroutines. We do not reply on general purpose malloc/free el=
isions.</div><div>We put a wording in the N4134 about it on purpose, so tha=
t we are free to do it.</div><div>Whether allocator is called or not is obs=
ervable, and thus do not fall under "as if" rule </div><div><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; paddi=
ng-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px=
; border-left-style: solid;">Finally, it just doesn't feel right having the=
compiler allocate
<br>outside of a library facility (the only other language feature,
<br></blockquote><div><br></div><div>Considered is to be similar to a new. =
Compiler does calls a library facility to do an allocation and then constru=
cts the object.</div><div>Very similar in this case.</div><div> </div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; paddi=
ng-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px=
; border-left-style: solid;">allocate is exception throwing; guess which is=
the first feature which
<br>is often prohibited in performance critical code?)
<br></blockquote><div><br></div><div>Hence a section in N4134 about using c=
oroutines in the environments where exceptions are not available or banned.=
</div><div> </div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204,=
204); border-left-width: 1px; border-left-style: solid;">so why are you pr=
oposing generators that are boxed by default ? :)
<br></blockquote><div><br></div><div>STL was not a zero overhead library in=
C++98.</div><div>It is now. Compilers caught up.</div><div>Luckily I am on=
a compiler team and I am a fan of coroutines. I think I can influence a li=
ttle bit our compiler to do the right job. :-) </div><div> </div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-le=
ft: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; bor=
der-left-style: solid;">Multi-pass iteration, backtracking, etc. .
<br></blockquote><div><br></div><div>This actions are not safe in a ge=
neral case, hence I am not proposing them now.</div><div>If there is e=
nough people pushing for them, it can be easily added later. </div><di=
v><br></div><div>One way to extend N4134 to allow that is to extend</div><d=
iv><br></div><div>resumable_handle (probably will rename it to coroutine_ha=
ndle) to add</div><div><br></div><div>coroutine_handle::clone() that clones=
the coroutine</div><div>coroutine_handle::save(buf)</div><div>coroutine_ha=
ndle::revive(buf)</div><div><br></div><div>or something like that. Then lib=
rary writer can use them to do whatever they think is needed.</div><div><br=
></div><div>Cheers,</div><div>Gor</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2276_1310152631.1414457273106--
.
Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Mon, 27 Oct 2014 20:38:26 -0700 (PDT)
Raw View
------=_Part_3788_1942300526.1414467506968
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
El martes, 28 de octubre de 2014 07:47:53 UTC+7, Gor Nishanov escribi=C3=B3=
:
>
> great :), so give us lambda*, then we will figure out what we can build=
=20
>> with it.=20
>>
>
> caught my usual compiler doing it in real world code, not even for=20
>> standard library types (string, function). Sure, it is nice to have,=20
>>
>
> Well, Microsoft compiler will do it. Other compiler better catch up :-) .
> =20
>
=20
I still don't get why we would like to get into the trouble of making,=20
enabling some fancy optimizations when in fact
a coroutine exposed as a function object is already easy to optimize=20
nowadays. Implementation of function object
mapping also seems easier for compiler vendors than, let's say, a heap=20
allocated block with all the optimizations
that must be coded to make it as nice as it can be. I don't see an=20
advantage in getting into trouble "for free" when
you can have something that is easier to support with essentially the same=
=20
functionality and a simpler implementation.
=20
> type support (and java is considering it), because it is so unreliable=20
>> in practice.=20
>>
>
> This is targeted optimization specific to coroutines. We do not reply on=
=20
> general purpose malloc/free elisions.
> We put a wording in the N4134 about it on purpose, so that we are free to=
=20
> do it.
> Whether allocator is called or not is observable, and thus do not fall=20
> under "as if" rule=20
>
> So this optimization, if I am not wrong, for a decent implementation, wil=
l=20
have to be coded. More work than just adopting
function objects, IMHO.
=20
> Finally, it just doesn't feel right having the compiler allocate=20
>> outside of a library facility (the only other language feature,=20
>>
>
> Considered is to be similar to a new. Compiler does calls a library=20
> facility to do an allocation and then constructs the object.
> Very similar in this case.
> =20
>
>> allocate is exception throwing; guess which is the first feature which=
=20
>> is often prohibited in performance critical code?)=20
>>
>
> Hence a section in N4134 about using coroutines in the environments where=
=20
> exceptions are not available or banned.=20
> =20
>
>> so why are you proposing generators that are boxed by default ? :)=20
>>
>
> STL was not a zero overhead library in C++98.
> It is now. Compilers caught up.
> Luckily I am on a compiler team and I am a fan of coroutines. I think I=
=20
> can influence a little bit our compiler to do the right job. :-)
>
I think that we have more than enough tools right now: reification is good.=
=20
We know function objects will enable all kind of optimizations
that, in the case of N4134 would have to be implemented by vendors. I don't=
=20
see this as an advantage, because, at least, for the
code I saw now, I don't find years ahead more usable N4134 compared to=20
N4244. Essentially, N4134 is "hiding" some runtime (memory alloc) behind=20
the scenes. Why would we want to do that when we have a simpler solution?
=20
> =20
>
>> Multi-pass iteration, backtracking, etc. .=20
>>
>
> This actions are not safe in a general case, hence I am not proposing the=
m=20
> now.
> If there is enough people pushing for them, it can be easily added later.=
=20
>
> One way to extend N4134 to allow that is to extend
>
> resumable_handle (probably will rename it to coroutine_handle) to add
>
> coroutine_handle::clone() that clones the coroutine
> coroutine_handle::save(buf)
> coroutine_handle::revive(buf)
>
> or something like that. Then library writer can use them to do whatever=
=20
> they think is needed.
>
The framework that is getting established in C++ is that of value-types=20
that behave
"just as ints", regular types, etc. They play well with concepts and=20
generic programming.
Trying to fit a separate, type-erased framework with another naming is a=20
mistake, IMHO.=20
Reification is one of the most powerful tools
that C++ has, because it keeps optimization oportunities such as inlining=
=20
feasible.=20
A coroutine type should be reified, because you can always erase a reified=
=20
type with a library
wrapper. On the other hand, a type that is already erased cannot be=20
"reified back".
For what I see in the standard library and what are considered=20
"well-behaved" types as in Stepanov's and
Sean Parent's material, this wouldn't look a standard way to do things IMHO=
..
Cheers,
> Gor
>
>
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_3788_1942300526.1414467506968
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>El martes, 28 de octubre de 2014 07:47:53 UTC+7, G=
or Nishanov escribi=C3=B3:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-widt=
h:1px;border-left-style:solid">great :), so give us lambda*, then we will f=
igure out what we can build with it.
<br></blockquote><div><br></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204=
);border-left-width:1px;border-left-style:solid">caught my usual comp=
iler doing it in real world code, not even for
<br>standard library types (string, function). Sure, it is nice to have,
<br></blockquote><div><br></div><div>Well, Microsoft compiler will do it. O=
ther compiler better catch up :-) .</div><div> </div></div></blockquot=
e><div> </div><div>I still don't get why we would like to get into the=
trouble of making, enabling some fancy optimizations when in fact</div><di=
v>a coroutine exposed as a function object is already easy to optimize nowa=
days. Implementation of function object</div><div>mapping also seems easier=
for compiler vendors than, let's say, a heap allocated block with all the =
optimizations</div><div>that must be coded to make it as nice as it can be.=
I don't see an advantage in getting into trouble "for free" when</div><div=
>you can have something that is easier to support with essentially the same=
functionality and a simpler implementation.</div><div> </div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left=
-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">type=
support (and java is considering it), because it is so unreliable
<br>in practice.
<br></blockquote><div><br></div><div>This is targeted optimization spe=
cific to coroutines. We do not reply on general purpose malloc/free el=
isions.</div><div>We put a wording in the N4134 about it on purpose, so tha=
t we are free to do it.</div><div>Whether allocator is called or not is obs=
ervable, and thus do not fall under "as if" rule </div><div><br></div>=
</div></blockquote><div>So this optimization, if I am not wrong, for a dece=
nt implementation, will have to be coded. More work than just adopting</div=
><div>function objects, IMHO.</div><div> </div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-col=
or:rgb(204,204,204);border-left-width:1px;border-left-style:solid">Finally,=
it just doesn't feel right having the compiler allocate
<br>outside of a library facility (the only other language feature,
<br></blockquote><div><br></div><div>Considered is to be similar to a new. =
Compiler does calls a library facility to do an allocation and then constru=
cts the object.</div><div>Very similar in this case.</div><div> </div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding=
-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-l=
eft-style:solid">allocate is exception throwing; guess which is the first f=
eature which
<br>is often prohibited in performance critical code?)
<br></blockquote><div><br></div><div>Hence a section in N4134 about using c=
oroutines in the environments where exceptions are not available or banned.=
</div><div> </div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);b=
order-left-width:1px;border-left-style:solid">so why are you proposing gene=
rators that are boxed by default ? :)
<br></blockquote><div><br></div><div>STL was not a zero overhead library in=
C++98.</div><div>It is now. Compilers caught up.</div><div>Luckily I am on=
a compiler team and I am a fan of coroutines. I think I can influence a li=
ttle bit our compiler to do the right job. :-)</div></div></blockquote><div=
><br></div><div>I think that we have more than enough tools right now: reif=
ication is good. We know function objects will enable all kind of optimizat=
ions</div><div>that, in the case of N4134 would have to be implemented by v=
endors. I don't see this as an advantage, because, at least, for the</div><=
div>code I saw now, I don't find years ahead more usable N4134 compared to =
N4244. Essentially, N4134 is "hiding" some runtime (memory alloc) behind th=
e scenes. Why would we want to do that when we have a simpler solution?</di=
v><div> </div><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> </div><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-=
left-width:1px;border-left-style:solid">Multi-pass iteration, backtracking,=
etc. .
<br></blockquote><div><br></div><div>This actions are not safe in a ge=
neral case, hence I am not proposing them now.</div><div>If there is e=
nough people pushing for them, it can be easily added later. </div><di=
v><br></div><div>One way to extend N4134 to allow that is to extend</div><d=
iv><br></div><div>resumable_handle (probably will rename it to coroutine_ha=
ndle) to add</div><div><br></div><div>coroutine_handle::clone() that clones=
the coroutine</div><div>coroutine_handle::save(buf)</div><div>coroutine_ha=
ndle::revive(buf)</div><div><br></div><div>or something like that. Then lib=
rary writer can use them to do whatever they think is needed.</div></div></=
blockquote><div><br></div><div>The framework that is getting established in=
C++ is that of value-types that behave</div><div>"just as ints", regular t=
ypes, etc. They play well with concepts and generic programming.</div><div>=
Trying to fit a separate, type-erased framework with another naming is a mi=
stake, IMHO. </div><div>Reification is one of the most powerful tools<=
/div><div>that C++ has, because it keeps optimization oportunities such as =
inlining feasible. </div><div><br></div><div>A coroutine type should b=
e reified, because you can always erase a reified type with a library</div>=
<div>wrapper. On the other hand, a type that is already erased cannot be "r=
eified back".</div><div>For what I see in the standard library and what are=
considered "well-behaved" types as in Stepanov's and</div><div>Sean Parent=
's material, this wouldn't look a standard way to do things IMHO.</div><div=
><br></div><div><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"ltr"><div>Cheers,</div><div>Gor</div><div><br></div></div></blockqu=
ote></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3788_1942300526.1414467506968--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 27 Oct 2014 21:34:20 -0700 (PDT)
Raw View
------=_Part_20_1254248513.1414470860710
Content-Type: text/plain; charset=UTF-8
N4134 makes a distinction between a coroutine, coroutine return object and
coroutine state.
Coroutine is a function or a lambda that can be suspended and resumed
preserving data local to the function / lambda.
Coroutine object is what you get when you call the coroutine and it is a
proper value type. Library author decide whether they want it to be movable
or copyable.
Coroutine state is stationary by design to remove restrictions on what you
can do in the body of the coroutine.
Making coroutine state mobile will place restriction on what you can do in
the body. You have to be cautions with things like std::function and
std::string that have small string / function optimizations as you may have
aliases to them which will be pointing to junk once you moved the coroutine
and you will not be able to use immovable types such as std::atomic and
std::mutex at all unless you heap allocate them and hold them by a
unique_ptr, for example.
I share your admiration for a beauty of well-behaved types, however, after
evaluating the consequences, I believe that N4134 is making the correct
trade-off by going for safety and not imposing any restrictions on what you
can and cannot do in the coroutine body.
Consider a string. It is a value type, but, it has heap allocation inside
and a small string optimization to mitigate the allocation cost. Similarly,
coroutine object is a handle to a stationary coroutine state, but heap
allocation can be elided in the cases where lifetime of the coroutine is
fully contained within lifetime of the calling function.
Cheers,
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_20_1254248513.1414470860710
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>N4134 makes a distinction between a coroutine, corout=
ine return object and coroutine state. </div><div>Coroutine is a function&n=
bsp;or a lambda that can be suspended and resumed preserving data local to =
the function / lambda.</div><div>Coroutine object is what you get=
when you call the coroutine and it is a proper value type. Libra=
ry author decide whether they want it to be movable or copyable.</div><div>=
Coroutine state is stationary by design to remove restrictions on what you =
can do in the body of the coroutine.</div><div>Making coroutine state mobil=
e will place restriction on what you can do in the body. You have to be cau=
tions with things like std::function and std::string that have small string=
/ function optimizations as you may have aliases to them which will b=
e pointing to junk once you moved the coroutine and you will not be able to=
use immovable types such as std::atomic and std::mutex at all unless you h=
eap allocate them and hold them by a unique_ptr, for example.</div><div><br=
></div><div>I share your admiration for a beauty of well-behaved types, how=
ever, after evaluating the consequences, I believe that N4134 is making the=
correct trade-off by going for safety and not imposing any restrictions on=
what you can and cannot do in the coroutine body.</div><div><br></div><div=
>Consider a string. It is a value type, but, it has heap allocation inside =
and a small string optimization to mitigate the allocation cost. Similarly,=
coroutine object is a handle to a stationary coroutine state, but hea=
p allocation can be elided in the cases where lifetime of the coroutine is =
fully contained within lifetime of the calling function.</div><div><br></di=
v><div>Cheers,</div><div>Gor</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_20_1254248513.1414470860710--
.
Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Tue, 28 Oct 2014 00:12:24 -0700 (PDT)
Raw View
------=_Part_1662_384394276.1414480344874
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
El martes, 28 de octubre de 2014 11:34:20 UTC+7, Gor Nishanov escribi=C3=B3=
:
>
> N4134 makes a distinction between a coroutine, coroutine return object an=
d=20
> coroutine state.=20
> Coroutine is a function or a lambda that can be suspended and resumed=20
> preserving data local to the function / lambda.=20
>
This one should be reified and reachable by the user without indirection.=
=20
Just as N4244. Just my opinion, of course.
=20
> Coroutine object is what you get when you call the coroutine and it is a=
=20
> proper value type. Library author decide whether they want it to be movab=
le=20
> or copyable.
>
I am not sure I follow this: this would be what exactly?
=20
> Coroutine state is stationary by design to remove restrictions on what yo=
u=20
> can do in the body of the coroutine.
>
I think this is the very thing that hurts performance opportunities with=20
current compiler technology, but I am not sure. This is the heap allocated=
=20
block if I am not wrong.
=20
> Making coroutine state mobile will place restriction on what you can do i=
n=20
> the body. You have to be cautions with things like std::function and=20
> std::string that have small string / function optimizations as you may ha=
ve=20
> aliases to them which will be pointing to junk once you moved the corouti=
ne=20
> and you will not be able to use immovable types such as std::atomic and=
=20
> std::mutex at all unless you heap allocate them and hold them by a=20
> unique_ptr, for example.
>
The same happens with normal types: put a mutex and you cannot copy or move=
=20
it anymore: this is consistent with what normal types do. I am not sure if=
=20
this problem is much worse in the case of coroutines, but I guess that yes.=
=20
I would explore these options, in order:
1. Making mutex (and others) movable. The semantics for mutex ummovable are=
=20
just semantic or are they a technical limitation?
We have the example of the proposed scope_guard: should not be movable, but=
=20
it is just to make it work correctly from factory functions,
and it is not a big deal in my opinion, compared to coding a new framework=
=20
allocators included to workaround this limitation.
2. Idea: why not turn around the semantics?=20
> I share your admiration for a beauty of well-behaved types, however, afte=
r=20
> evaluating the consequences, I believe that N4134 is making the correct=
=20
> trade-off by going for safety and not imposing any restrictions on what y=
ou=20
> can and cannot do in the coroutine body.
>
=20
Go for it, you are the implementor and I see you do believe in your design=
=20
and implementation. :) I still think that this tradeoff has more=20
consequences: in generic contexts it is nice to be able to copy/move and=20
equality-compare coroutines. Think of even serializing coroutines to=20
network, saving to disk (equality compare?), storing in containers,=20
embedding as data members... the possibilities are endless with=20
value-types.=20
=20
> Consider a string. It is a value type, but, it has heap allocation inside=
=20
> and a small string optimization to mitigate the allocation cost. Similarl=
y,=20
> coroutine object is a handle to a stationary coroutine state, but heap=20
> allocation can be elided in the cases where lifetime of the coroutine is=
=20
> fully contained within lifetime of the calling function.
>
> Unfortunately, with the design for N4134 we need other things, even if=20
there are tradeoffs:
- An allocator by default (such as erased std::function, since you dont=20
know the size). I think this is not the best choice. It should be avoided.
- Some compiler optimizations we cannot safely rely on: vs function=20
objects, which can easily be inlined etc. and optimizers already deal well=
=20
with them, I think this will impose more implementation costs and having to=
=20
rely on QoI, which, without doubt, in the case of Microsoft would be good,=
=20
hehe. But there are more compilers.
=20
Regards
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1662_384394276.1414480344874
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>El martes, 28 de octubre de 2014 11:34:20 UTC+7, G=
or Nishanov escribi=C3=B3:<blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div>N4134 makes a distinction between a coroutine, coroutine=
return object and coroutine state. </div><div>Coroutine is a function =
;or a lambda that can be suspended and resumed preserving data local to the=
function / lambda. </div></div></blockquote><div>This one should=
be reified and reachable by the user without indirection. Just as N4244. J=
ust my opinion, of course.</div><div> <br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div>Coroutine object is what you&n=
bsp;get when you call the coroutine and it is a proper value type=
.. Library author decide whether they want it to be movable or copyable.</di=
v></div></blockquote><div>I am not sure I follow this: this would be what e=
xactly?</div><div> </div><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>Coroutine state is stationary by design to remove res=
trictions on what you can do in the body of the coroutine.</div></div></blo=
ckquote><div>I think this is the very thing that hurts performance opportun=
ities with current compiler technology, but I am not sure. This is th=
e heap allocated block if I am not wrong.</div><div> </div><blockquote=
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>Making coroutine st=
ate mobile will place restriction on what you can do in the body. You have =
to be cautions with things like std::function and std::string that have sma=
ll string / function optimizations as you may have aliases to them whi=
ch will be pointing to junk once you moved the coroutine and you will not b=
e able to use immovable types such as std::atomic and std::mutex at all unl=
ess you heap allocate them and hold them by a unique_ptr, for example.</div=
></div></blockquote><div><br></div><div><br></div><div>The same happens wit=
h normal types: put a mutex and you cannot copy or move it anymore: this is=
consistent with what normal types do. I am not sure if this problem is muc=
h worse in the case of coroutines, but I guess that yes. </div><div><b=
r></div><div>I would explore these options, in order:</div><div><br></div><=
div>1. Making mutex (and others) movable. The semantics for mutex ummovable=
are just semantic or are they a technical limitation?</div><div>We have th=
e example of the proposed scope_guard: should not be movable, but it is jus=
t to make it work correctly from factory functions,</div><div>and it is not=
a big deal in my opinion, compared to coding a new framework allocators in=
cluded to workaround this limitation.</div><div><br></div><div>2. Idea: why=
not turn around the semantics? </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>I share your admiration for a beauty of =
well-behaved types, however, after evaluating the consequences, I believe t=
hat N4134 is making the correct trade-off by going for safety and not impos=
ing any restrictions on what you can and cannot do in the coroutine body.</=
div></div></blockquote><div> </div><div>Go for it, you are the impleme=
ntor and I see you do believe in your design and implementation. :) I still=
think that this tradeoff has more consequences: in generic contexts it is =
nice to be able to copy/move and equality-compare coroutines. Think of even=
serializing coroutines to network, saving to disk (equality compare?), sto=
ring in containers, embedding as data members... the possibilities are endl=
ess with value-types. </div><div><br></div><div> </div><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>Consider a string.=
It is a value type, but, it has heap allocation inside and a small string =
optimization to mitigate the allocation cost. Similarly, coroutine object i=
s a handle to a stationary coroutine state, but heap allocation can be=
elided in the cases where lifetime of the coroutine is fully contained wit=
hin lifetime of the calling function.</div><div><br></div></div></blockquot=
e><div>Unfortunately, with the design for N4134 we need other things, even =
if there are tradeoffs:</div><div><br></div><div>- An allocator by default =
(such as erased std::function, since you dont know the size). I think this =
is not the best choice. It should be avoided.</div><div>- Some compiler opt=
imizations we cannot safely rely on: vs function objects, which can easily =
be inlined etc. and optimizers already deal well with them, I think this wi=
ll impose more implementation costs and having to rely on QoI, which, witho=
ut doubt, in the case of Microsoft would be good, hehe. But there are more =
compilers.</div><div> </div><div>Regards</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1662_384394276.1414480344874--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 28 Oct 2014 09:25:20 +0200
Raw View
On 28 October 2014 09:12, Germ=C3=A1n Diago <germandiago@gmail.com> wrote:
>> Making coroutine state mobile will place restriction on what you can do =
in
>> the body. You have to be cautions with things like std::function and
>> std::string that have small string / function optimizations as you may h=
ave
>> aliases to them which will be pointing to junk once you moved the corout=
ine
>> and you will not be able to use immovable types such as std::atomic and
>> std::mutex at all unless you heap allocate them and hold them by a
>> unique_ptr, for example.
> The same happens with normal types: put a mutex and you cannot copy or mo=
ve
> it anymore: this is consistent with what normal types do. I am not sure i=
f
> this problem is much worse in the case of coroutines, but I guess that ye=
s.
I guess not. Just because a resumable lambda that has a mutex in its body
cannot be moved doesn't mean you necessarily need to move the lambda.
The difference between N4134 and N4244 is that with the former, you would
never even attempt to move non-movable state in the coroutine because you
can't access that state so directly - all you see is the return type
of the coroutine.
With N4244, you can (albeit indirectly) see both the return type and the st=
ate.
> I would explore these options, in order:
> 1. Making mutex (and others) movable. The semantics for mutex ummovable a=
re
> just semantic or are they a technical limitation?
It is a semantic limitation. I don't see any reason to lift it just
because a resumable
lambda cannot be moved if it contains a mutex. If coroutines cannot cope wi=
th
unmovable types, the solution is not to make everything movable; the soluti=
on
is to throw coroutines under the bus. But, as I said, not being able to mo=
ve
such a resumable lambda is a red herring, it's not likely to be a
practical limitation.
N4244 explains what you need to do in such cases, and those restrictions
seem fine to me.
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Tue, 28 Oct 2014 02:53:02 -0700 (PDT)
Raw View
------=_Part_1210_1397075565.1414489982333
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 28, 2014 12:47:53 AM UTC, Gor Nishanov wrote:
>
> great :), so give us lambda*, then we will figure out what we can build
>> with it.
>>
>
> Having N4134 does not preclude exposing lambda* later if there are use
> cases for it and unsolved yet issues with lambda* / N4244 are resolved.
> (Page 6 last paragraph)
>
I have already discussed the use cases. Regarding the problems, I'm on the
opinion that those are really non issues. A generator with non copyable
local variables would simply be non copyable. I think this won't happen
very often as most types are at least movable; regarding the usual
suspects, could you find a non contrived example in which you would want to
use a std::mutex or an std::atomic as a local object?
>
>
>
>> [...] windows, due an ABI less friendly to this usage, compiler support
>> could help even more.
>>
>
> I am not sure how compiler can help. Oliver's assembly routines are as
> fast as you can get for stackful context switch:
> *https://github.com/Beman/boost-trunk-git-svn/blob/master/libs/context/src/asm/jump_x86_64_ms_pe_masm.asm*
> <https://github.com/Beman/boost-trunk-git-svn/blob/master/libs/context/src/asm/jump_x86_64_ms_pe_masm.asm>
>
>
the compiler can help by saving only those registers which are actually
changed in the function body. See GCC extended asm syntax and explicit
clobbers (and that's still not optimal). Oliver's assembly is very likely
the best he could do given the constraints of that specific
compiler/platform, but is provably not optimal as I can get better
performance on similar hardware with a different compiler.
>
>> so, will a compiler be able to unbox if I put the generator in an
>> std::option? boost::variant?
>>
>
> If there is no suspension needed, such as with optional, there is no
> coroutine frame at all.
> It is a normal function in all aspects. No need for allocation elision at
> all.
>
type support (and java is considering it), because it is so unreliable
>> in practice.
>>
>
> This is targeted optimization specific to coroutines. We do not reply on
> general purpose malloc/free elisions.
>
We put a wording in the N4134 about it on purpose, so that we are free to
> do it.
>
That doesn't magically make it easier.
std::generator<int> foo_gen() {... yield 1; ...}
void bar()
{
std::optional<std::generator<int> > x ;
if(make_generator)
x = foo_gen();
...
}
replace optional with boost::variant, std::vector, or any other container.
Can MSVC guarantee no additional heap allocation in all cases?
Note I'm not even sure whether the above code is supposed to compile and
what its semantics would be. Is resumable_handle a value type? can it be
moved? Can it be copied? If yes does it perform deep copying or shallow
copying via reference counting? The paper is silent on these issues.
What about this:
void baz(generator<int>&) ; // external function, potentially in a DLL
void bar()
{
generator<int> x = foo_gen();
baz(x);
... // keep using x
}
Can the compiler elide the allocation? What if baz moves out or replaces
the content of x? That's a reduced example, but in the real world there are
many surprising ways in which the address of a local object may escape.
Again, without whole program analysis everything but trivial examples
cannot be optimized.
Whether allocator is called or not is observable, and thus do not fall
> under "as if" rule
>
C++11 explicitly allows an implementation to elide calls to new/delete. It
is understood that a compiler has always been able to replace call to
malloc/free, in the same way it can replace any of the C library functions
with builtins.
>
> Finally, it just doesn't feel right having the compiler allocate
>> outside of a library facility (the only other language feature,
>>
>
> Considered is to be similar to a new. Compiler does calls a library
> facility to do an allocation and then constructs the object.
> Very similar in this case.
>
>
>> allocate is exception throwing; guess which is the first feature which
>> is often prohibited in performance critical code?)
>>
>
> Hence a section in N4134 about using coroutines in the environments where
> exceptions are not available or banned.
>
>
>> so why are you proposing generators that are boxed by default ? :)
>>
>
> STL was not a zero overhead library in C++98.
>
It is now. Compilers caught up.
>
yes and it took them 10 years. Will we have to wait till 2027 before being
able to use coroutines? N4244 leverages optimizations that C++ compilers
are already exceptionally good at.
Also the abstraction elimination required for STL was mostly aggressive
inlining and scalar replacement of aggregates, which are relatively "local"
optimizations. The escape analysis required to optimize away allocation in
all but trivial cases potentially require whole program compilation.
> Luckily I am on a compiler team and I am a fan of coroutines. I think I
> can influence a little bit our compiler to do the right job. :-)
>
*cough* can you influence them to get their c++11 implementation completed
first? *cough* :)
>
>
>> Multi-pass iteration, backtracking, etc. .
>>
>
> This actions are not safe in a general case, hence I am not proposing them
> now.
> If there is enough people pushing for them, it can be easily added later.
>
why would they be not safe? They are perfectly safe in N4244 design. As
safe as the rest of the c++ at least. Also their semantics do not even need
to be specified explicitly: their behaviour derived directly from the
underlying type the generator desugars to.
BTW, please take my comments as constructive criticism. I think what you
guys are doing is great stuff, I just think it can be improved :)
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1210_1397075565.1414489982333
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, October 28, 2014 12:47:53 AM UTC, Gor =
Nishanov 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=
"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;paddi=
ng-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border=
-left-style:solid">great :), so give us lambda*, then we will figure out wh=
at we can build with it.
<br></blockquote><div><br></div><div>Having N4134 does not preclude exposin=
g lambda* later if there are use cases for it and unsolved yet issues with =
lambda* / N4244 are resolved. (Page 6 last paragraph)</div></div></blockquo=
te><div><br>I have already discussed the use cases. Regarding the problems,=
I'm on the opinion that those are really non issues. A generator with non =
copyable local variables would simply be non copyable. I think this won't h=
appen very often as most types are at least movable; regarding the usual su=
spects, could you find a non contrived example in which you would want to u=
se a std::mutex or an std::atomic as a local object? <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><br></div>=
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px =
0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-w=
idth:1px;border-left-style:solid">[...]
windows, due an ABI less friendly to this usage, compiler support
<br>could help even more.
<br></blockquote><div><br></div><div>I am not sure how compiler can help. O=
liver's assembly routines are as fast as you can get for stackful context s=
witch: <span style=3D"color:rgb(31,73,125);font-family:"Calibri",=
"sans-serif";font-size:11pt"><a href=3D"https://github.com/Beman/=
boost-trunk-git-svn/blob/master/libs/context/src/asm/jump_x86_64_ms_pe_masm=
..asm" target=3D"_blank" onmousedown=3D"this.href=3D'https://www.google.com/=
url?q\75https%3A%2F%2Fgithub.com%2FBeman%2Fboost-trunk-git-svn%2Fblob%2Fmas=
ter%2Flibs%2Fcontext%2Fsrc%2Fasm%2Fjump_x86_64_ms_pe_masm.asm\46sa\75D\46sn=
tz\0751\46usg\75AFQjCNGIZ58rpLEok2zeJ7kLk5K7vzKxqQ';return true;" onclick=
=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2F=
Beman%2Fboost-trunk-git-svn%2Fblob%2Fmaster%2Flibs%2Fcontext%2Fsrc%2Fasm%2F=
jump_x86_64_ms_pe_masm.asm\46sa\75D\46sntz\0751\46usg\75AFQjCNGIZ58rpLEok2z=
eJ7kLk5K7vzKxqQ';return true;"><u><font color=3D"#0000ff">https://github.co=
m/Beman/<wbr>boost-trunk-git-svn/blob/<wbr>master/libs/context/src/asm/<wbr=
>jump_x86_64_ms_pe_masm.asm</font></u></a></span></div><div><br></div></div=
></blockquote><div><br>the compiler can help by saving only those registers=
which are actually changed in the function body. See GCC extended asm synt=
ax and explicit clobbers (and that's still not optimal). Oliver's assembly =
is very likely the best he could do given the constraints of that specific =
compiler/platform, but is provably not optimal as I can get better performa=
nce on similar hardware with a different compiler.<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><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;b=
order-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:s=
olid"><br>so, will a compiler be able to unbox if I put the generator in an
<br>std::option? boost::variant?
<br></blockquote><div><br></div><div>If there is no suspension needed, such=
as with optional, there is no coroutine frame at all.</div><div>It is a no=
rmal function in all aspects. No need for allocation elision at all.</div><=
/div></blockquote><div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1p=
x;border-left-style:solid">type support (and java is considering it), becau=
se it is so unreliable
<br>in practice.
<br></blockquote><div><br></div><div>This is targeted optimization spe=
cific to coroutines. We do not reply on general purpose malloc/free el=
isions. <br></div></div></blockquote><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>We put a wording in the N4134 about it on purp=
ose, so that we are free to do it.</div></div></blockquote> <br>That d=
oesn't magically make it easier.<br></div><div><br>std::generator<int>=
; foo_gen() {... yield 1; ...}<br><br>void bar()<br>{<br> =
std::optional<std::generator<int> > x ;<br><br> if=
(make_generator)<br> x =3D foo_gen();<br>&nbs=
p; ...<br>}<br><br>replace optional with boost::variant, std::vector, or an=
y other container. Can MSVC guarantee no additional heap allocation i=
n all cases? <br><br>Note I'm not even sure whether the above code is suppo=
sed to compile and what its semantics would be. Is resumable_handle a value=
type? can it be moved? Can it be copied? If yes does it perform deep copyi=
ng or shallow copying via reference counting? The paper is silent on these =
issues.<br><br>What about this:<br><br>void baz(generator<int>&) =
; // external function, potentially in a DLL<br><br>void bar()<br>{<br>&nbs=
p; generator<int> x =3D foo_gen();<br><br> baz(x);<=
br> ... // keep using x<br>}<br><br>Can the compiler elide the alloca=
tion? What if baz moves out or replaces the content of x? That's a reduced =
example, but in the real world there are many surprising ways in which the =
address of a local object may escape. Again, without whole program analysis=
everything but trivial examples cannot be optimized.<br></div><br><blockqu=
ote 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>Whether allocato=
r is called or not is observable, and thus do not fall under "as if" rule&n=
bsp;</div></div></blockquote><div><br>C++11 explicitly allows an implementa=
tion to elide calls to new/delete. It is understood that a compiler has alw=
ays been able to replace call to malloc/free, in the same way it can replac=
e any of the C library functions with builtins.<br> </div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;=
border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:=
solid">Finally, it just doesn't feel right having the compiler allocate
<br>outside of a library facility (the only other language feature,
<br></blockquote><div><br></div><div>Considered is to be similar to a new. =
Compiler does calls a library facility to do an allocation and then constru=
cts the object.</div><div>Very similar in this case.</div><div> </div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding=
-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-l=
eft-style:solid">allocate is exception throwing; guess which is the first f=
eature which
<br>is often prohibited in performance critical code?)
<br></blockquote><div><br></div><div>Hence a section in N4134 about using c=
oroutines in the environments where exceptions are not available or banned.=
</div><div> </div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);b=
order-left-width:1px;border-left-style:solid">so why are you proposing gene=
rators that are boxed by default ? :)
<br></blockquote><div><br></div><div>STL was not a zero overhead library in=
C++98. <br></div></div></blockquote><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>It is now. Compilers caught up.</div></div></b=
lockquote><div><br>yes and it took them 10 years. Will we have to wait till=
2027 before being able to use coroutines? N4244 leverages optimizations th=
at C++ compilers are already exceptionally good at. <br><br>Also the abstra=
ction elimination required for STL was mostly aggressive inlining and scala=
r replacement of aggregates, which are relatively "local" optimizations. Th=
e escape analysis required to optimize away allocation in all but trivial c=
ases potentially require whole program compilation.<br> </div><blockqu=
ote 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>Luckily I am on =
a compiler team and I am a fan of coroutines. I think I can influence a lit=
tle bit our compiler to do the right job. :-) </div></div></blockquote><div=
><br>*cough* can you influence them to get their c++11 implementation compl=
eted first? *cough* :)<br> </div><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><blockquote class=3D"gmail_quote"=
style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(2=
04,204,204);border-left-width:1px;border-left-style:solid">Multi-pass itera=
tion, backtracking, etc. .
<br></blockquote><div><br></div><div>This actions are not safe in a ge=
neral case, hence I am not proposing them now.</div><div>If there is e=
nough people pushing for them, it can be easily added later. </div></d=
iv></blockquote><div><br>why would they be not safe? They are perfectly saf=
e in N4244 design. As safe as the rest of the c++ at least. Also thei=
r semantics do not even need to be specified explicitly: their behaviour de=
rived directly from the underlying type the generator desugars to.<br></div=
><br>BTW, please take my comments as constructive criticism. I think what y=
ou guys are doing is great stuff, I just think it can be improved :)<br><br=
></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1210_1397075565.1414489982333--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Tue, 28 Oct 2014 03:00:52 -0700 (PDT)
Raw View
------=_Part_135_123525515.1414490452907
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Tuesday, October 28, 2014 7:12:24 AM UTC, Germ=C3=A1n Diago wrote:
>
> 1. Making mutex (and others) movable. The semantics for mutex ummovable=
=20
> are just semantic or are they a technical limitation?
>
It doesn't make sense to move a mutex as it is its address that is=20
relevant. But for the same reason, there are no use cases for a movable=20
mutex (and very very few uses as a local object).=20
-- gpd
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_135_123525515.1414490452907
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tuesday, October 28, 2014 7:12:24 AM UTC, Germ=C3=A1n D=
iago 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">1.=
Making mutex (and others) movable. The semantics for mutex ummovable are j=
ust semantic or are they a technical limitation?</div></blockquote><div><br=
>It doesn't make sense to move a mutex as it is its address that is relevan=
t. But for the same reason, there are no use cases for a movable mutex (and=
very very few uses as a local object). <br></div><br>-- gpd<br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_135_123525515.1414490452907--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 28 Oct 2014 12:33:57 +0200
Raw View
On 28 October 2014 12:00, Giovanni Piero Deretta <gpderetta@gmail.com> wrot=
e:
> On Tuesday, October 28, 2014 7:12:24 AM UTC, Germ=C3=A1n Diago wrote:
>>
>> 1. Making mutex (and others) movable. The semantics for mutex ummovable
>> are just semantic or are they a technical limitation?
>
>
> It doesn't make sense to move a mutex as it is its address that is releva=
nt.
> But for the same reason, there are no use cases for a movable mutex (and
> very very few uses as a local object).
Even if the address of a mutex wouldn't be relevant, moving a mutex would a=
llow
moving a mutex across threads. Such shenanigans make no sense whatsoever. ;=
)
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Tue, 28 Oct 2014 06:10:07 -0700 (PDT)
Raw View
------=_Part_4040_886394770.1414501807538
Content-Type: text/plain; charset=UTF-8
Ville:
I started with the design similar to N4244, I called it lambda* and after
experimenting with it I came to a conclusion that syntactic sugar on top,
such as N4134 is necessary for convenience and safety.
Conceptually, there is an unspecified lambda* sitting inside of N4134,
leaving it unspecified allows to do more optimization than what would be
possible.
> it's not likely to be a practical limitation.
> N4244 explains what you need to do in such cases, and those restrictions
> seem fine to me.
>
I believe that having a stationary coroutine state is important to do async
I/O patterns efficiently and with minimal number of extraneous heap
allocations.
To achieve that you need to place lambda* / N4244 on a heap or embed it in
some other heap allocated class or a global variable.
Either embedding (example in section 5 of N4244) or allocating it on the
heap, will require a move.
Look at the steps involve.
1st we need to make a helper function returning a lambda.
auto foo() { return []() resumable { ....} };
than, for the case of embedded, you will say:
struct Parent {
decltype(foo()) foo_;
Parent(decltype(foo()) foo) : foo_(std::move(foo)) {} // move?
I also considered moving a lambda* that start executing unsafe in general
case, due to aliases to local state of the running / suspended coroutine
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4040_886394770.1414501807538
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Ville:</div><div><br></div><div><div>I started with t=
he design similar to N4244, I called it lambda* and after experimenting wit=
h it I came to a conclusion that syntactic sugar on top, such as N4134 is n=
ecessary for convenience and safety.</div><div> </div><div>Conceptuall=
y, there is an unspecified lambda* sitting inside of N4134, leaving it=
unspecified allows to do more optimization than what would be possible. </=
div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border=
-left-width: 1px; border-left-style: solid;">it's not likely to be a
practical limitation.
<br>N4244 explains what you need to do in such cases, and those restriction=
s
<br>seem fine to me.
<br></blockquote><div><br></div><div>I believe that having a stationary cor=
outine state is important to do async I/O patterns efficiently and with min=
imal number of extraneous heap allocations.</div><div>To achieve that you n=
eed to place lambda* / N4244 on a heap or embed it in some other heap alloc=
ated class or a global variable.</div><div><br></div><div>Either embe=
dding (example in section 5 of N4244) or allocating it on the heap, will re=
quire a move.</div><div><br></div><div>Look at the steps involve.</div><div=
><br></div><div>1st we need to make a helper function returning a lambda.</=
div><div><br></div><div>auto foo() { return []() resumable { ....} }; </div=
><div><br></div><div>than, for the case of embedded, you will say:</div><di=
v><br></div><div>struct Parent {</div><div> decltyp=
e(foo()) foo_;</div><div> Parent(decltype(foo()) fo=
o) : foo_(std::move(foo)) {} // move?</div><div><br></div><div><br></div><d=
iv>I also considered moving a lambda* that start executing unsafe in genera=
l case, due to aliases to local state of the running / suspended coroutine<=
/div><div><br></div><div><br></div><div><br></div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4040_886394770.1414501807538--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 28 Oct 2014 15:22:59 +0200
Raw View
On 28 October 2014 15:10, Gor Nishanov <gornishanov@gmail.com> wrote:
> Ville:
>
> I started with the design similar to N4244, I called it lambda* and after
> experimenting with it I came to a conclusion that syntactic sugar on top,
> such as N4134 is necessary for convenience and safety.
I know, you've said so before. :)
> Conceptually, there is an unspecified lambda* sitting inside of N4134,
> leaving it unspecified allows to do more optimization than what would be
> possible.
Well, there's less stuff revealed to the user. Sorta. Kinda. The
detailed implementation
of a N4244 lambda is not exposed either, although you can copy/move the lambda
if you want to. If such copies/moves are not attempted, I would expect
an advanced
implementation to be able to optimize as much as with N4134. N4134 is
also restricted
in what exactly it can do optimization-wise, because I can certainly
detect when it
destroys the things in its state and what order when I destroy the
return value (which
controls the lifetime of the state).
>> it's not likely to be a practical limitation.
>> N4244 explains what you need to do in such cases, and those restrictions
>> seem fine to me.
> I believe that having a stationary coroutine state is important to do async
> I/O patterns efficiently and with minimal number of extraneous heap
> allocations.
> To achieve that you need to place lambda* / N4244 on a heap or embed it in
> some other heap allocated class or a global variable.
No, I need to place the stationary state on the heap and refer to that
state from
the lambda. That's rather easy, I don't need to pass extra arguments
to the lambda,
I can just capture what I need to refer to. I don't need to place the
lambda itself on
the heap. Also, I don't quite grasp why such heap allocations are
necessary in cases
where the lambda outlives the async operations.
It seems to me that N4134 trades off allocation flexibility for safety
- users can't mess
up the allocation of the state. N4244 allows the user to decide where
that state will
live, and can even muck with it directly. I find the information about
optimization
possibilities.. ..inconclusive.
Anyway, that's rather positive - most of the differences between these
proposals that
people are worried about seem to be nuances rather than completely
opposite views.
The negative side of that is difficulty in trying to make a decision
which to adopt. ;)
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Tue, 28 Oct 2014 06:24:20 -0700 (PDT)
Raw View
------=_Part_4048_1559880506.1414502660361
Content-Type: text/plain; charset=UTF-8
>
> *cough* can you influence them to get their c++11 implementation completed
> first? *cough* :)
>
:-) Developer works best when they are scratching their own "itch". I spent
15+ years doing scalable high performance I/O with hand-crafted state
machines. That is my pain, N4134 removes the pain and make async
programming much more pleasurable and more efficient as well.
Stationary frame for the coroutine opens up programming techniques not
possible before. If you consider novel patterns enabled by it, you will
discover that having a mutex or atomic as a local variable or passing an
address to a local to an outside world is perfectly reasonable and can
bring you performance gains.
>
> why would they be not safe? They are perfectly safe in N4244 design. As
> safe as the rest of the c++ at least.
>
Notice that lambda* transforms the variables form the body of operator()()
in a member variable of the class. Aliases may appear without you noticing;
std::string s = "hello";
for(ch: S) yield ch;
Now lambda* executed one iteration and yielded a value.
You move lambda* to a new location.
Somewhere inside of the range-based-for there is an iterator pointing to
buffer of std::string. Because "hello" is small, it is subject to
small-string optimization and thus iterator points at the coroutine frame.
It is invisible to developer, when lambda* was relocated and resumed,
iterator points at garbage.
Cheers,
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4048_1559880506.1414502660361
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div>*cough*=
can you influence them to get their c++11 implementation completed first? =
*cough* :)</div></div></blockquote><div><br></div><div>:-) Developer works =
best when they are scratching their own "itch". I spent 15+ years doing sca=
lable high performance I/O with hand-crafted state machines. That is my pai=
n, N4134 removes the pain and make async programming much more pleasurable =
and more efficient as well.</div><div><br></div><div>Stationary frame for t=
he coroutine opens up programming techniques not possible before. If you co=
nsider novel patterns enabled by it, you will discover that having a mutex =
or atomic as a local variable or passing an address to a local to an outsid=
e world is perfectly reasonable and can bring you performance gains.</div><=
div><br></div><div> </div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 20=
4, 204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr=
"><div> <br>why would they be not safe? They are perfectly safe in N42=
44 design. As safe as the rest of the c++ at least.</div></div></bloc=
kquote><div><br></div><div>Notice that lambda* transforms the variables for=
m the body of operator()() in a member variable of the class. Aliases may a=
ppear without you noticing;</div><div><br></div><div>std::string s =3D "hel=
lo";</div><div>for(ch: S) yield ch;</div><div><br></div><div>Now lambda* ex=
ecuted one iteration and yielded a value. </div><div>You move lambda* to a =
new location.</div><div>Somewhere inside of the range-based-for there is an=
iterator pointing to buffer of std::string. Because "hello" is small, it i=
s subject to small-string optimization and thus iterator points at the coro=
utine frame.</div><div><br></div><div>It is invisible to developer, when la=
mbda* was relocated and resumed, iterator points at garbage.</div><div><br>=
</div><div>Cheers,</div><div>Gor<br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4048_1559880506.1414502660361--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Tue, 28 Oct 2014 15:30:35 +0200
Raw View
On 28 October 2014 15:24, Gor Nishanov <gornishanov@gmail.com> wrote:
> Notice that lambda* transforms the variables form the body of operator()()
> in a member variable of the class. Aliases may appear without you noticing;
>
> std::string s = "hello";
> for(ch: S) yield ch;
>
> Now lambda* executed one iteration and yielded a value.
> You move lambda* to a new location.
> Somewhere inside of the range-based-for there is an iterator pointing to
> buffer of std::string. Because "hello" is small, it is subject to
> small-string optimization and thus iterator points at the coroutine frame.
>
> It is invisible to developer, when lambda* was relocated and resumed,
> iterator points at garbage.
Ouch. I would love to hear what Chris thinks as a solution for such problems.
Such situations are going to be a bitch to debug _and_ reason about,
since there's
really nothing in the code that would suggest that such things might happen.
People tend to be surprised when you pull the rug from under their feet. :)
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Tue, 28 Oct 2014 07:00:25 -0700 (PDT)
Raw View
------=_Part_1371_1794402965.1414504825296
Content-Type: text/plain; charset=UTF-8
On Tuesday, October 28, 2014 1:24:20 PM UTC, Gor Nishanov wrote:
>
>
>
>>
>> why would they be not safe? They are perfectly safe in N4244 design. As
>> safe as the rest of the c++ at least.
>>
>
> Notice that lambda* transforms the variables form the body of operator()()
> in a member variable of the class. Aliases may appear without you noticing;
>
> std::string s = "hello";
> for(ch: S) yield ch;
>
>
hargh, that's pretty damning. You do not even need the string:
char s[] = "hello";
for(ch: S) yield ch;
for this specific case the compiler *could* fix the iterator, but you can
come up with other cases in which it is unfeasible. I agree that making
generator copyable by default would be terribly error prone.
There might be a way out that might satisfy everybody's requirements. Let
me think about 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1371_1794402965.1414504825296
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, October 28, 2014 1:24:20 PM UTC, Gor N=
ishanov 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><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-=
width:1px;border-left-style:solid"><div dir=3D"ltr"><div> <br>why woul=
d they be not safe? They are perfectly safe in N4244 design. As safe =
as the rest of the c++ at least.</div></div></blockquote><div><br></div><di=
v>Notice that lambda* transforms the variables form the body of operator()(=
) in a member variable of the class. Aliases may appear without you noticin=
g;</div><div><br></div><div>std::string s =3D "hello";</div><div>for(ch: S)=
yield ch;</div><div><br></div></div></blockquote><div><br>hargh, that's pr=
etty damning. You do not even need the string:<br> <br><div> cha=
r s[] =3D "hello";</div><div> for(ch: S) yield ch;</div><div><br>for =
this specific case the compiler *could* fix the iterator, but you can come =
up with other cases in which it is unfeasible. I agree that making generato=
r copyable by default would be terribly error prone.<br></div></div><br>The=
re might be a way out that might satisfy everybody's requirements. Let me t=
hink about it.<br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1371_1794402965.1414504825296--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Tue, 28 Oct 2014 14:09:32 -0700 (PDT)
Raw View
------=_Part_20_1988729987.1414530572891
Content-Type: text/plain; charset=UTF-8
Ville:
Short:
Difference is stylistic, and in the choice of defaults: (i.e safe vs easy
to copy), (requires an allocator to mock with allocation or a state is
value type you can manipulate directly).
Performance wise and functionality wise I believe they are equivalent.
If there were no N4134, I would be strongly in favor of N4244, I am tired
of hand-writing state machine N4244.
Given a choice between *N3977*
<http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3977.pdf> and N4244,
I would have also picked N4244. N3977 lacked degree of customizability I
desired. N4244 gives me that.
Now, at this point, it is hard to be unbiased, between N4134 and N4244, I
would choose N4134. :-)
Long:
N4134 has three faces.
Novice face. Somebody else written generator, task, etc, coroutine types
(possibly standardized and part of standard library). Your experience is as
good or better as any other programming languages that have coroutines.
Easy teaching, easy learning.
Intermediate face: Okay, you want to adapt await to new types, well, you
have to learn those three magical names: await_ready, await_suspend and
await_resume, go party!
Hard core face: Okay, if you are serious you have full control, invent new
coroutine types that world have never seen, add support for stateful
allocators, tune default allocator for your coroutine to nearly match
stackful coroutine performance where number of recursive invocations of
coroutines outweights the more expensive context switch cost).
Okay, enough selling. What are the differences:
Difference and mostly stylistic. Frequently, you would need to write a
wrapper of sorts around N4244. N4134 automates that. So, less typing and
(subjectively prettier syntax)
N4244 makes if easier to copy and move the state. N4134 make it harder. But
I can see if there is a strong desire and compelling use cases it can be
extended to allow cloning() of a suspended coroutine, or relocating the
suspended coroutine with the caveat that it would not be always possible
and would not be always safe.
I think for any problem there will be a solution using N4134 and N4244 that
will be equally performant. N4134 might be less typing and
I am not sure if as described, N4244 can match all of the use cases of
N4134, but I can imagine how N4244 can be evolved to match them.
necessary in cases
where the lambda outlives the async operations.
>> live, and can even muck with it directly. I find the information about
optimization
>> possibilities.. ..inconclusive.
It was easier to optimize on our compiler as of today:-) . I do not think
that is necessarily so for other compilers and as compiler evolve I do not
believe there will be any performance difference.
>> The negative side of that is difficulty in trying to make a decision
which to adopt. ;)
I know, if not for N4134 I would have jumped up and down to get N4244 as
soon as possible.
One way how I can reconcile the difference is that since N4134 is
conceptually build on top of something like N4244 (though it is
unspecified), adopting N4134 does not preclude to exposing machinery later
if there is a strong use case for it.
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_20_1988729987.1414530572891
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Ville:</div><div><br></div><div>Short:</div><div><br>=
</div><div>Difference is stylistic, and in the choice of defaults: (i.e saf=
e vs easy to copy), (requires an allocator to mock with allocation or =
a state is value type you can manipulate directly).</div><div>Performance w=
ise and functionality wise I believe they are equivalent. <br></div><div><b=
r></div><div>If there were no N4134, I would be strongly in favor of N4244,=
I am tired of hand-writing state machine N4244. </div><div>Given a choice =
between <a href=3D"http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n397=
7.pdf"><u><font color=3D"#0066cc">N3977</font></u></a> and N4244, I wo=
uld have also picked N4244. N3977 lacked degree of customizability I desire=
d. N4244 gives me that.</div><div>Now, at this point, it is hard to be unbi=
ased, between N4134 and N4244, I would choose N4134. :-)</div><div><br></di=
v><div>Long:</div><div><br></div><div>N4134 has three faces.</div><div><br>=
</div><div>Novice face. Somebody else written generator, task, etc, corouti=
ne types (possibly standardized and part of standard library). Your experie=
nce is as good or better as any other programming languages that have corou=
tines. Easy teaching, easy learning.</div><div><br></div><div>Intermediate =
face: Okay, you want to adapt await to new types, well, you have to learn t=
hose three magical names: await_ready, await_suspend and await_resume, go p=
arty!</div><div><br></div><div>Hard core face: Okay, if you are serious you=
have full control, invent new coroutine types that world have never seen, =
add support for stateful allocators, tune default allocator for your corout=
ine to nearly match stackful coroutine performance where number of recursiv=
e invocations of coroutines outweights the more expensive context switch co=
st). </div><div><br></div><div>Okay, enough selling. What are the differenc=
es:</div><div><br></div><div><div>Difference and mostly stylistic. Frequent=
ly, you would need to write a wrapper of sorts around N4244. N4134 automate=
s that. So, less typing and (subjectively prettier syntax)</div><div>N4244 =
makes if easier to copy and move the state. N4134 make it harder. But I can=
see if there is a strong desire and compelling use cases it can be extende=
d to allow cloning() of a suspended coroutine, or relocating the suspe=
nded coroutine with the caveat that it would not be always possible and wou=
ld not be always safe.</div><div><br></div><div>I think for any problem the=
re will be a solution using N4134 and N4244 that will be equally performant=
.. N4134 might be less typing and </div><div>I am not sure if=
as described, N4244 can match all of the use cases of N4134, but I ca=
n imagine how N4244 can be evolved to match them. </div></di=
v><div>necessary in cases
<br>where the lambda outlives the async operations.
<br>
<br>>> live, and can even muck with it directly. I find the informati=
on about
optimization
<br>>> possibilities.. ..inconclusive.
<br>
</div><div><br></div><div>It was easier to optimize on our compiler as of t=
oday:-) . I do not think that is necessarily so for other compilers and as =
compiler evolve I do not believe there will be any performance difference.<=
/div><div><br>>> The negative side of that is difficulty in trying to=
make a decision
which to adopt. ;)
</div><div><br></div><div>I know, if not for N4134 I would have jumped up a=
nd down to get N4244 as soon as possible.</div><div>One way how I can recon=
cile the difference is that since N4134 is conceptually build on top of som=
ething like N4244 (though it is unspecified), adopting N4134 does not precl=
ude to exposing machinery later if there is a strong use case for it.<=
/div><div><br></div><div>Gor<br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_20_1988729987.1414530572891--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Tue, 28 Oct 2014 14:19:40 -0700 (PDT)
Raw View
------=_Part_498_1068364236.1414531180468
Content-Type: text/plain; charset=UTF-8
>
> > It is invisible to developer, when lambda* was relocated and resumed,
> > iterator points at garbage.
>
>
> Ouch.
>
This was one of the use cases that led me to believe that I need to hide
lambda* under a safe and pretty face of a resumable function.
Another reason was that I wanted to amortize various allocations you need
to do in async programming letting them be a temporary on a stationary
coroutine frame.
And also, enshrining allocation elision for the coroutine frame in the
standard, allows to remove the negative aspects of "safe by default"
decision.
Another plug for stationary frames:
Stationary coroutine frame opens the possibility to provide RAII for
asynchrony. That is something that was sorely missing and was a great pain
to deal with.
Now it can finally happen. Woot!
Note: stationary frames are possible in N4244 as well. Just wrap the
lambda* into a helper function and do make_unique<decltype(foo())>(foo())
and you are good to go.
Gor
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_498_1068364236.1414531180468
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;">> It is invisible to devel=
oper, when lambda* was relocated and resumed,
<br>> iterator points at garbage.
<br>
<br>
<br>Ouch. <br></blockquote><div><br></div><div>This was one of the use case=
s that led me to believe that I need to hide lambda* under a safe and prett=
y face of a resumable function.</div><div>Another reason was that I wanted =
to amortize various allocations you need to do in async programming le=
tting them be a temporary on a stationary coroutine frame.</div><div>And al=
so, enshrining allocation elision for the coroutine frame in the standard, =
allows to remove the negative aspects of "safe by default" decision.</div><=
div><br></div><div>Another plug for stationary frames:</div><div><br></div>=
<div>Stationary coroutine frame opens the possibility to provide RAII for a=
synchrony. That is something that was sorely missing and was a great pain t=
o deal with.</div><div>Now it can finally happen. Woot!</div><div><br></div=
><div>Note: stationary frames are possible in N4244 as well. Just wrap the =
lambda* into a helper function and do make_unique<decltype(foo())>(fo=
o()) and you are good to go.</div><div><br></div><div>Gor</div><div><br></d=
iv><div>Gor</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_498_1068364236.1414531180468--
.
Author: =?UTF-8?Q?Germ=C3=A1n_Diago?= <germandiago@gmail.com>
Date: Wed, 29 Oct 2014 02:48:58 -0700 (PDT)
Raw View
------=_Part_2628_1236174573.1414576138414
Content-Type: text/plain; charset=UTF-8
>
>
> One way how I can reconcile the difference is that since N4134 is
> conceptually build on top of something like N4244 (though it is
> unspecified), adopting N4134 does not preclude to exposing machinery later
> if there is a strong use case for it.
>
I would like to see N4244 as a language feature and, if later a higher
level framework is needed it could be built on top of it, but: would we
need await/yield integrated into the language at that point?
Maybe a standard class to hold the resumable lambdas globally and hide them
would be better than integrating something directly into the language, such
as await, since doing that "marries you" to that implementation choice
forever. Another thing I don't quite like either is to have to wrap types
in futures or generators. In N4244 you can return ints directly, for
example.
Of course, these are my personal, selfish wishes ;) Hope we have the
coroutines with the highest performance possible, without any sacrifices
and relying as little as possible on new compiler tech.
Gor
>
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2628_1236174573.1414576138414
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<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"l=
tr"><div><br></div><div>One way how I can reconcile the difference is that =
since N4134 is conceptually build on top of something like N4244 (though it=
is unspecified), adopting N4134 does not preclude to exposing machinery la=
ter if there is a strong use case for it.</div></div></blockquote><div=
><br></div><div>I would like to see N4244 as a language feature and, if lat=
er a higher level framework is needed it could be built on top of it, but: =
would we need await/yield integrated into the language at that point? =
</div><div>Maybe a standard class to hold the resumable lambdas globally an=
d hide them would be better than integrating something directly into the la=
nguage, such as await, since doing that "marries you" to that implementatio=
n choice forever. Another thing I don't quite like either is to have to wra=
p types in futures or generators. In N4244 you can return ints directly, fo=
r example.</div><div><br></div><div>Of course, these are my personal, selfi=
sh wishes ;) Hope we have the coroutines with the highest performance possi=
ble, without any sacrifices and relying as little as possible on new compil=
er tech.</div><div><br></div><div><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div>Gor<br></div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2628_1236174573.1414576138414--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 29 Oct 2014 12:14:15 +0200
Raw View
On 29 October 2014 11:48, Germ=C3=A1n Diago <germandiago@gmail.com> wrote:
> forever. Another thing I don't quite like either is to have to wrap types=
in
> futures or generators. In N4244 you can return ints directly, for example=
..
Well, yes, that irks me too. An N4244 resumable lambda can indeed return
plain ints, writing a simple generator with it is very simple and there's n=
o
wrapper type involved.
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Christopher Kohlhoff <chris@kohlhoff.com>
Date: Thu, 30 Oct 2014 00:42:02 +1100
Raw View
--089e0158c09aca0ec305068fed62
Content-Type: text/plain; charset=UTF-8
On Wed, Oct 29, 2014 at 1:00 AM, Giovanni Piero Deretta <gpderetta@gmail.com
> wrote:
>
>
> On Tuesday, October 28, 2014 1:24:20 PM UTC, Gor Nishanov wrote:
>>
>>
>>
>>>
>>> why would they be not safe? They are perfectly safe in N4244 design. As
>>> safe as the rest of the c++ at least.
>>>
>>
>> Notice that lambda* transforms the variables form the body of
>> operator()() in a member variable of the class. Aliases may appear without
>> you noticing;
>>
>> std::string s = "hello";
>> for(ch: S) yield ch;
>>
>>
> hargh, that's pretty damning. You do not even need the string:
>
> char s[] = "hello";
> for(ch: S) yield ch;
>
> for this specific case the compiler *could* fix the iterator, but you can
> come up with other cases in which it is unfeasible. I agree that making
> generator copyable by default would be terribly error prone.
>
> There might be a way out that might satisfy everybody's requirements. Let
> me think about it.
>
By way of background let me say that I disagree with Gor's definition
of "stackless" as his definition includes N4134 coroutines. The
defining characteristic of stackless coroutines is that, as a user, you
make no assumptions about the stack:
- You make no assumptions that your variables have stable addresses.
- You don't do things that alias your local variables.
As soon as you stick that little "resumable" keyword on there, you are
defining an aggregate where the data members are defined as locals.
But yes, range-based for is a problem because it necessarily introduces
aliasing and yet also hides it away. It seems to me there's a simple
solution: If your resumable lambda contains a ranged-based for, and
your range-based for contains a yield, then the resumable lambda's copy
and move constructors are inhibited. Nothing of value is lost. In other
words, we can still write:
std::vector<std::string> strings;
...
auto&& f = [strings]
{
for (auto s: strings)
yield s;
...
};
if we are willing to accept that f is noncopyable. Please note that in
my implementation I have solved the problem of noncopyable lambdas. You
can run the lambda as a stationary object in your preferred location --
heap, stack or data member -- and not just as a lifetime-extended
temporary.
Inhibiting copyability in the presence of ranged-based for is about
maintaining correctness. I don't believe copyable or movable coroutines
are particularly error prone in general, and the yield points where one
must take care are explicitly documented in the source code. Field
experience with macro-based coroutines bears this out.
It might appear tempting to make noncopyability the default, though
whether or not there is a quantifiable benefit in doing so is
questionable. However, to insist that, due to a perception of risk,
resumable lambdas must reside on the heap is to throw the baby out with
the bath water. To me this approach seems fundamentally at odds with
the ethos and existing practice of C++. A compiler vendor knows far far
less about the specifics of the applications we develop than we do. I
use C++ because I know more about my application, because I care about
performance, and because C++ gives me flexibility to apply this
knowledge.
Lastly, the stated position that having a stationary frame means that
we must have heap allocations smells like faulty logic to me. A
stationary frame implies only that the object not be copied or moved.
C++ programmers write noncopyable classes every day, and they are
perfectly able to put them on the stack, embed them as data members in
other classes, and so on.
Cheers,
Chris
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0158c09aca0ec305068fed62
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Oct 29, 2014 at 1:00 AM, Giovanni Piero Deretta <span dir=3D"lt=
r"><<a href=3D"mailto:gpderetta@gmail.com" target=3D"_blank">gpderetta@g=
mail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span=
class=3D""><br><br>On Tuesday, October 28, 2014 1:24:20 PM UTC, Gor Nishan=
ov wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;borde=
r-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid=
"><div dir=3D"ltr"><div>=C2=A0<br>why would they be not safe? They are perf=
ectly safe in N4244 design.=C2=A0 As safe as the rest of the c++ at least.<=
/div></div></blockquote><div><br></div><div>Notice that lambda* transforms =
the variables form the body of operator()() in a member variable of the cla=
ss. Aliases may appear without you noticing;</div><div><br></div><div>std::=
string s =3D "hello";</div><div>for(ch: S) yield ch;</div><div><b=
r></div></div></blockquote></span><div><br>hargh, that's pretty damning=
.. You do not even need the string:<br>=C2=A0<br><div>=C2=A0 char s[] =3D &q=
uot;hello";</div><div>=C2=A0 for(ch: S) yield ch;</div><div><br>for th=
is specific case the compiler *could* fix the iterator, but you can come up=
with other cases in which it is unfeasible. I agree that making generator =
copyable by default would be terribly error prone.<br></div></div><br>There=
might be a way out that might satisfy everybody's requirements. Let me=
think about it.<br></div></blockquote><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb=
(204,204,204);border-left-style:solid;padding-left:1ex"><div class=3D""><di=
v class=3D"h5"></div></div></blockquote></div><br></div><div class=3D"gmail=
_extra"><div class=3D"gmail_extra">By way of background let me say that I d=
isagree with Gor's definition</div><div class=3D"gmail_extra">of "=
stackless" as his definition includes N4134 coroutines. The</div><div =
class=3D"gmail_extra">defining characteristic of stackless coroutines is th=
at, as a user, you</div><div class=3D"gmail_extra">make no assumptions abou=
t the stack:</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_=
extra">- You make no assumptions that your variables have stable addresses.=
</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">- You=
don't do things that alias your local variables.</div><div class=3D"gm=
ail_extra"><br></div><div class=3D"gmail_extra">As soon as you stick that l=
ittle "resumable" keyword on there, you are</div><div class=3D"gm=
ail_extra">defining an aggregate where the data members are defined as loca=
ls.</div><div class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">Bu=
t yes, range-based for is a problem because it necessarily introduces</div>=
<div class=3D"gmail_extra">aliasing and yet also hides it away. It seems to=
me there's a simple</div><div class=3D"gmail_extra">solution: If your =
resumable lambda contains a ranged-based for, and</div><div class=3D"gmail_=
extra">your range-based for contains a yield, then the resumable lambda'=
;s copy</div><div class=3D"gmail_extra">and move constructors are inhibited=
.. Nothing of value is lost. In other</div><div class=3D"gmail_extra">words,=
we can still write:</div><div class=3D"gmail_extra"><br></div><div class=
=3D"gmail_extra">=C2=A0 std::vector<std::string> strings;</div><div c=
lass=3D"gmail_extra">=C2=A0 ...</div><div class=3D"gmail_extra">=C2=A0 auto=
&& f =3D [strings]</div><div class=3D"gmail_extra">=C2=A0 {</div><d=
iv class=3D"gmail_extra">=C2=A0 =C2=A0 for (auto s: strings)</div><div clas=
s=3D"gmail_extra">=C2=A0 =C2=A0 =C2=A0 yield s;</div><div class=3D"gmail_ex=
tra">=C2=A0 =C2=A0 ...</div><div class=3D"gmail_extra">=C2=A0 };</div><div =
class=3D"gmail_extra"><br></div><div class=3D"gmail_extra">if we are willin=
g to accept that f is noncopyable. Please note that in</div><div class=3D"g=
mail_extra">my implementation I have solved the problem of noncopyable lamb=
das. You</div><div class=3D"gmail_extra">can run the lambda as a stationary=
object in your preferred location --</div><div class=3D"gmail_extra">heap,=
stack or data member -- and not just as a lifetime-extended</div><div clas=
s=3D"gmail_extra">temporary.</div><div class=3D"gmail_extra"><br></div><div=
class=3D"gmail_extra">Inhibiting copyability in the presence of ranged-bas=
ed for is about</div><div class=3D"gmail_extra">maintaining correctness. I =
don't believe copyable or movable coroutines</div><div class=3D"gmail_e=
xtra">are particularly error prone in general, and the yield points where o=
ne</div><div class=3D"gmail_extra">must take care are explicitly documented=
in the source code. Field</div><div class=3D"gmail_extra">experience with =
macro-based coroutines bears this out.</div><div class=3D"gmail_extra"><br>=
</div><div class=3D"gmail_extra">It might appear tempting to make noncopyab=
ility the default, though</div><div class=3D"gmail_extra">whether or not th=
ere is a quantifiable benefit in doing so is</div><div class=3D"gmail_extra=
">questionable. However, to insist that, due to a perception of risk,</div>=
<div class=3D"gmail_extra">resumable lambdas must reside on the heap is to =
throw the baby out with</div><div class=3D"gmail_extra">the bath water. To =
me this approach seems fundamentally at odds with</div><div class=3D"gmail_=
extra">the ethos and existing practice of C++. A compiler vendor knows far =
far</div><div class=3D"gmail_extra">less about the specifics of the applica=
tions we develop than we do. I</div><div class=3D"gmail_extra">use C++ beca=
use I know more about my application, because I care about</div><div class=
=3D"gmail_extra">performance, and because C++ gives me flexibility to apply=
this</div><div class=3D"gmail_extra">knowledge.</div><div class=3D"gmail_e=
xtra"><br></div><div class=3D"gmail_extra">Lastly, the stated position that=
having a stationary frame means that</div><div class=3D"gmail_extra">we mu=
st have heap allocations smells like faulty logic to me. A</div><div class=
=3D"gmail_extra">stationary frame implies only that the object not be copie=
d or moved.</div><div class=3D"gmail_extra">C++ programmers write noncopyab=
le classes every day, and they are</div><div class=3D"gmail_extra">perfectl=
y able to put them on the stack, embed them as data members in</div><div cl=
ass=3D"gmail_extra">other classes, and so on.</div><div class=3D"gmail_extr=
a"><br></div><div class=3D"gmail_extra">Cheers,</div><div class=3D"gmail_ex=
tra">Chris</div><div><br></div></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0158c09aca0ec305068fed62--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Wed, 29 Oct 2014 07:36:36 -0700 (PDT)
Raw View
------=_Part_4929_1838284002.1414593396159
Content-Type: text/plain; charset=UTF-8
>
> Lastly, the stated position that having a stationary frame means that
> we must have heap allocations smells like faulty logic to me.
>
I agree with you. You can get stationary coroutine frame in at least three
ways:
1. use an allocator to dynamically select the place where coroutine frame
will live: could be on the heap, in the global or on the stack, depending
on the allocator
2. on the stack or another coroutine frame, when coroutine lifetime is
fully contained within the lifetime of its caller
3. embedded into another object
N4134 options #1 and #2 comes for free, for #3 you have to work to make it
happen (muck around with allocators)
N4244 options #2 comes for free, for #1 and #3 you need to work just a
little
Chris, did you notice me praising 4244, before :-) ?
Gor earlier: If there were no N4134, I would be strongly in favor of N4244,
I am tired of hand-writing state machine N4244.
Given a choice between *N3977*
<http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3977.pdf> and N4244,
I would have also picked N4244. N3977 lacked degree of customizability I
desired. N4244 gives me 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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4929_1838284002.1414593396159
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div><div>La=
stly, the stated position that having a stationary frame means that</div><d=
iv>we must have heap allocations smells like faulty logic to me. </div></di=
v></div></blockquote><div><br></div><div>I agree with you. You can get stat=
ionary coroutine frame in at least three ways:</div><div><br></div><div>1. =
use an allocator to dynamically select the place where coroutine frame will=
live: could be on the heap, in the global or on the stack, depending on th=
e allocator</div><div>2. on the stack or another coroutine frame, when coro=
utine lifetime is fully contained within the lifetime of its caller</div><d=
iv>3. embedded into another object</div><div><br></div><div>N4134 opti=
ons #1 and #2 comes for free, for #3 you have to work to make it happen (mu=
ck around with allocators)</div><div>N4244 options #2 comes for free, for #=
1 and #3 you need to work just a little</div><div><br></div><div>Chris, did=
you notice me praising 4244, before :-) ?</div><div><br></div><div><div>Go=
r earlier: If there were no N4134, I would be strongly in favor of N4244, I=
am tired of hand-writing state machine N4244. </div><div>Given a choice be=
tween <a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%=
2F%2Fopen-std.org%2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2014%2Fn3977.pdf\4=
6sa\75D\46sntz\0751\46usg\75AFQjCNEqYjQ8sO_lnlX8mUej5zIc8kOyuw';return true=
;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fopen-=
std.org%2FJTC1%2FSC22%2FWG21%2Fdocs%2Fpapers%2F2014%2Fn3977.pdf\46sa\75D\46=
sntz\0751\46usg\75AFQjCNEqYjQ8sO_lnlX8mUej5zIc8kOyuw';return true;" href=3D=
"http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3977.pdf" target=3D"_=
blank"><u><font color=3D"#0066cc">N3977</font></u></a> and N4244, I wo=
uld have also picked N4244. N3977 lacked degree of customizability I desire=
d. N4244 gives me that.</div><div><br></div></div><div><br></div>
</div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4929_1838284002.1414593396159--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Wed, 29 Oct 2014 16:38:40 +0200
Raw View
On 29 October 2014 15:42, Christopher Kohlhoff <chris@kohlhoff.com> wrote:
> But yes, range-based for is a problem because it necessarily introduces
> aliasing and yet also hides it away. It seems to me there's a simple
> solution: If your resumable lambda contains a ranged-based for, and
> your range-based for contains a yield, then the resumable lambda's copy
> and move constructors are inhibited. Nothing of value is lost. In other
> words, we can still write:
>
> std::vector<std::string> strings;
> ...
> auto&& f = [strings]
> {
> for (auto s: strings)
> yield s;
> ...
> };
>
> if we are willing to accept that f is noncopyable. Please note that in
> my implementation I have solved the problem of noncopyable lambdas. You
> can run the lambda as a stationary object in your preferred location --
> heap, stack or data member -- and not just as a lifetime-extended
> temporary.
>
> Inhibiting copyability in the presence of ranged-based for is about
> maintaining correctness. I don't believe copyable or movable coroutines
> are particularly error prone in general, and the yield points where one
> must take care are explicitly documented in the source code. Field
> experience with macro-based coroutines bears this out.
What about the other forms of such aliasing? range-for is certainly not the
only way to cause such problems.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Wed, 29 Oct 2014 07:41:59 -0700 (PDT)
Raw View
------=_Part_352_1142617175.1414593719779
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 29, 2014 1:42:06 PM UTC, Christopher Kohlhoff wrote:
> On Wed, Oct 29, 2014 at 1:00 AM, Giovanni Piero Deretta <gpde...@gmail.com
> <javascript:>> wrote:
>
>> On Tuesday, October 28, 2014 1:24:20 PM UTC, Gor Nishanov wrote:
>>>
>>> why would they be not safe? They are perfectly safe in N4244 design. As
>>> safe as the rest of the c++ at least.
>>>
>>> Notice that lambda* transforms the variables form the body of
>>> operator()() in a member variable of the class. Aliases may appear without
>>> you noticing;
>>>
>>> std::string s = "hello";
>>> for(ch: S) yield ch;
>>>
>>>
>> hargh, that's pretty damning. You do not even need the string:
>>
>> char s[] = "hello";
>> for(ch: S) yield ch;
>>
>> for this specific case the compiler *could* fix the iterator, but you can
>> come up with other cases in which it is unfeasible. I agree that making
>> generator copyable by default would be terribly error prone.
>>
>> There might be a way out that might satisfy everybody's requirements. Let
>> me think about it.
>>
>
> By way of background let me say that I disagree with Gor's definition
> of "stackless" as his definition includes N4134 coroutines. The
> defining characteristic of stackless coroutines is that, as a user, you
> make no assumptions about the stack:
>
well, the term "stackless coroutine", to diferentiate it from "stackful
coroutine", comes form the paper "Revisiting Coroutines" by De Moura et
al., where the distinction comes from the ability to suspend exactly one
frame versus an arbitrary amount of stack frames. Per that definition,
those in N4134, N4244, python and C# are stackless coroutines, while those
in Oliver's paper, Lua, Posix and Windows are stackful.
>
> - You make no assumptions that your variables have stable addresses.
>
> - You don't do things that alias your local variables.
>
> As soon as you stick that little "resumable" keyword on there, you are
> defining an aggregate where the data members are defined as locals.
>
agree, but...
>
> But yes, range-based for is a problem because it necessarily introduces
> aliasing and yet also hides it away. It seems to me there's a simple
> solution: If your resumable lambda contains a ranged-based for, and
> your range-based for contains a yield, then the resumable lambda's copy
> and move constructors are inhibited.
>
.... at this point I'm concerned that there might be other common idioms
that would break with generators via hidden aliasing. Even local references
to other local variables would break depending on whether the compiler
compiles the reference away or lowers it to a pointer. Compilers could warn
when a reference to a local variable survives across a yield point, but
such an analysis would necessarily be approximate.
> It might appear tempting to make noncopyability the default, though
> whether or not there is a quantifiable benefit in doing so is
> questionable. However, to insist that, due to a perception of risk,
> resumable lambdas must reside on the heap is to throw the baby out with
> the bath water. To me this approach seems fundamentally at odds with
> the ethos and existing practice of C++. A compiler vendor knows far far
> less about the specifics of the applications we develop than we do. I
> use C++ because I know more about my application, because I care about
> performance, and because C++ gives me flexibility to apply this
> knowledge.
>
> Lastly, the stated position that having a stationary frame means that
> we must have heap allocations smells like faulty logic to me. A
> stationary frame implies only that the object not be copied or moved.
> C++ programmers write noncopyable classes every day, and they are
> perfectly able to put them on the stack, embed them as data members in
> other classes, and so on.
>
I agree completely about this. In the worst case that we will need to make
generators always noncopyable/nonmovable, there is still no need for them
to be heap allocated by default.
For my use cases, I would perfectly happy to heap allocate coroutine
control blocks for async I/O, but I would not want the type to be erased so
that I can allocate them out of an memory pool of fixed chunks and I do not
have to rely on the compiler to perform devirtualization.
The other important case for me that coroutines need to solve well is
generators:
// assuming a range enabled standard library and overloads of begin() and
end() for generators
template<class Range, class Predicate>
auto filter(Range&& r, Predicate p) { return [&r, p]{ for(x : r if (p(x)
yield x; }; }
std::vector<int> numbers;
std::vector<int> odd (filter(numbers, [](auto x){ return x % 2});
filter wouldn't compile today because it needs a copy/move constructor
which would be disabled (although the iteratable is not owned by the
generator); a language change would fix that (requiring the construction of
the return value inplace when returning a lambda/generator expression
directly). Lack of copyability would also prevent the generator to,
somewhat surprisingly, match the Range concept (at least as presented in
N4128).
-- gpd
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_352_1142617175.1414593719779
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, October 29, 2014 1:42:06 PM UTC, Christopher=
Kohlhoff wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote">On Wed, Oct 29, 2014 at 1:00 AM, G=
iovanni Piero Deretta <span dir=3D"ltr"><<a href=3D"javascript:" target=
=3D"_blank" gdf-obfuscated-mailto=3D"VnQF63au8U0J" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;">gpde...@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmai=
l_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-lef=
t-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=
=3D"ltr"><span>On Tuesday, October 28, 2014 1:24:20 PM UTC, Gor Nishanov wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:sol=
id;padding-left:1ex"><div dir=3D"ltr"><div dir=3D"ltr"><div>why would they =
be not safe? They are perfectly safe in N4244 design. As safe as the =
rest of the c++ at least.</div></div><div><br></div><div>Notice that lambda=
* transforms the variables form the body of operator()() in a member variab=
le of the class. Aliases may appear without you noticing;</div><div><br></d=
iv><div>std::string s =3D "hello";</div><div>for(ch: S) yield ch;</div><div=
><br></div></div></blockquote></span><div><br>hargh, that's pretty damning.=
You do not even need the string:<br> <br><div> char s[] =3D "he=
llo";</div><div> for(ch: S) yield ch;</div><div><br>for this specific=
case the compiler *could* fix the iterator, but you can come up with other=
cases in which it is unfeasible. I agree that making generator copyable by=
default would be terribly error prone.<br></div></div><br>There might be a=
way out that might satisfy everybody's requirements. Let me think about it=
..<br></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);b=
order-left-style:solid;padding-left:1ex"><div><div></div></div></blockquote=
></div><br></div><div><div>By way of background let me say that I disagree =
with Gor's definition</div><div>of "stackless" as his definition includes N=
4134 coroutines. The</div><div>defining characteristic of stackless corouti=
nes is that, as a user, you</div><div>make no assumptions about the stack:<=
/div></div></div></blockquote><div><br>well, the term "stackless coroutine"=
, to diferentiate it from "stackful coroutine", comes form the paper "Revis=
iting Coroutines" by De Moura et al., where the distinction comes from the =
ability to suspend exactly one frame versus an arbitrary amount of stack fr=
ames. Per that definition, those in N4134, N4244, python and C# are s=
tackless coroutines, while those in Oliver's paper, Lua, Posix and Windows =
are stackful.<br> </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><div><br></div><div>- You make no assumptions that you=
r variables have stable addresses.</div><div><br></div><div>- You don't do =
things that alias your local variables.</div><div><br></div><div>As soon as=
you stick that little "resumable" keyword on there, you are</div><div>defi=
ning an aggregate where the data members are defined as locals.</div></div>=
</div></blockquote><div><br>agree, but...<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><br></div><div>Bu=
t yes, range-based for is a problem because it necessarily introduces</div>=
<div>aliasing and yet also hides it away. It seems to me there's a simple</=
div><div>solution: If your resumable lambda contains a ranged-based for, an=
d</div><div>your range-based for contains a yield, then the resumable lambd=
a's copy</div><div>and move constructors are inhibited. <br></div></div></d=
iv></blockquote><div><br>... at this point I'm concerned that there might b=
e other common idioms that would break with generators via hidden aliasing.=
Even local references to other local variables would break depending on wh=
ether the compiler compiles the reference away or lowers it to a pointer. C=
ompilers could warn when a reference to a local variable survives across a =
yield point, but such an analysis would necessarily be approximate. <br>&nb=
sp;</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=
><div></div><div>It might appear tempting to make noncopyability the defaul=
t, though</div><div>whether or not there is a quantifiable benefit in doing=
so is</div><div>questionable. However, to insist that, due to a perception=
of risk,</div><div>resumable lambdas must reside on the heap is to throw t=
he baby out with</div><div>the bath water. To me this approach seems fundam=
entally at odds with</div><div>the ethos and existing practice of C++. A co=
mpiler vendor knows far far</div><div>less about the specifics of the appli=
cations we develop than we do. I</div><div>use C++ because I know more abou=
t my application, because I care about</div><div>performance, and because C=
++ gives me flexibility to apply this</div><div>knowledge.</div><div><br></=
div><div>Lastly, the stated position that having a stationary frame means t=
hat</div><div>we must have heap allocations smells like faulty logic to me.=
A</div><div>stationary frame implies only that the object not be copied or=
moved.</div><div>C++ programmers write noncopyable classes every day, and =
they are</div><div>perfectly able to put them on the stack, embed them as d=
ata members in</div><div>other classes, and so on.</div></div></div></block=
quote><div><br>I agree completely about this. In the worst case that we wil=
l need to make generators always noncopyable/nonmovable, there is still no =
need for them to be heap allocated by default.<br><br>For my use case=
s, I would perfectly happy to heap allocate coroutine control blocks for as=
ync I/O, but I would not want the type to be erased so that I can allocate =
them out of an memory pool of fixed chunks and I do not have to rely on the=
compiler to perform devirtualization. <br><br>The other important case for=
me that coroutines need to solve well is generators:<br><br> // assu=
ming a range enabled standard library and overloads of begin() and end() fo=
r generators<br> template<class Range, class Predicate><br>&nbs=
p; auto filter(Range&& r, Predicate p) { return [&r, p]{ for(x =
: r if (p(x) yield x; }; }<br><br> std::vector<int> numbers;<br=
> std::vector<int> odd (filter(numbers, [](auto x){ return x % =
2});<br><br>filter wouldn't compile today because it needs a copy/move cons=
tructor which would be disabled (although the iteratable is not owned by th=
e generator); a language change would fix that (requiring the construction =
of the return value inplace when returning a lambda/generator expression di=
rectly). Lack of copyability would also prevent the generator to, somewhat =
surprisingly, match the Range concept (at least as presented in N4128).<br>=
<br>-- gpd<br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_352_1142617175.1414593719779--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Wed, 29 Oct 2014 07:52:52 -0700 (PDT)
Raw View
------=_Part_5914_108358063.1414594372193
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Wednesday, October 29, 2014 3:14:17 AM UTC-7, Ville Voutilainen wrote:
>
> On 29 October 2014 11:48, Germ=C3=A1n Diago <germa...@gmail.com <javascri=
pt:>>=20
> wrote:=20
> > forever. Another thing I don't quite like either is to have to wrap=20
> types in=20
> > futures or generators. In N4244 you can return ints directly, for=20
> example.=20
>
> Well, yes, that irks me too.=20
>
One of the great things about STL that iterator (and soon Iterable)=20
abstraction allows to mix and match. Hookup different algorithms,=20
containers, filters together and work seamlessly and efficiently.
Iterable "wrapper" around a generator allows STL to consume generators=20
directly, you can filter them using boost-range-adapters, you can use it to=
=20
add stuff / initiate container and many more things, you can copy them=20
directly to io-streams.
Wrapper, means that your coroutine is pluggable into existing (and future)=
=20
environments that may or may not be aware of coroutines at all but can=20
seamlessly interact with them.
(Without imposing overhead, of course. Gor is a high-level abstractions=20
with zero-overhead zealot) :-)
=20
--=20
---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_5914_108358063.1414594372193
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, October 29, 2014 3:14:17 AM UTC-7, V=
ille Voutilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0=
px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204);=
border-left-width: 1px; border-left-style: solid;">On 29 October 2014 11:4=
8, Germ=C3=A1n Diago <<a onmousedown=3D"this.href=3D'javascript:';return=
true;" onclick=3D"this.href=3D'javascript:';return true;" href=3D"javascri=
pt:" target=3D"_blank" gdf-obfuscated-mailto=3D"shcsMENUBBgJ">germa...@gmai=
l.com</a>> wrote:
<br>> forever. Another thing I don't quite like either is to have to wra=
p types in
<br>> futures or generators. In N4244 you can return ints directly, for =
example.
<br>
<br>Well, yes, that irks me too. <br></blockquote><div><br></div><div>One o=
f the great things about STL that iterator (and soon Iterable) abstrac=
tion allows to mix and match. Hookup different algorithms, contai=
ners, filters together and work seamlessly and efficiently.</div><div><br><=
/div><div>Iterable "wrapper" around a generator allows STL t=
o consume generators directly, you can filter them using boost-range-a=
dapters, you can use it to add stuff / initiate container and many more thi=
ngs, you can copy them directly to io-streams.</div><div><br></div><div>Wra=
pper, means that your coroutine is pluggable into existing (and future) env=
ironments that may or may not be aware of coroutines at all but can se=
amlessly interact with them.</div><div>(Without imposing overhead, of cours=
e. Gor is a high-level abstractions with zero-overhead zealot) :-)</div><di=
v><br></div><div> </div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5914_108358063.1414594372193--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Wed, 29 Oct 2014 08:02:13 -0700 (PDT)
Raw View
------=_Part_6741_623376695.1414594933709
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 29, 2014 2:36:36 PM UTC, Gor Nishanov wrote:
>
> Lastly, the stated position that having a stationary frame means that
>> we must have heap allocations smells like faulty logic to me.
>>
>
> I agree with you. You can get stationary coroutine frame in at least three
> ways:
>
> 1. use an allocator to dynamically select the place where coroutine frame
> will live: could be on the heap, in the global or on the stack, depending
> on the allocator
> 2. on the stack or another coroutine frame, when coroutine lifetime is
> fully contained within the lifetime of its caller
> 3. embedded into another object
>
> N4134 options #1 and #2 comes for free, for #3 you have to work to make it
> happen (muck around with allocators)
>
#1: the current allocator support relies on the generator result type and
parameters. The decision to which allocator (and whether to use one) should
not be statically keyed to the signature. Also not knowing the size of the
buffer at compile time prevent some optimizations. Neither of these
problems are of course unsurmountable, but I would look for a different
customization strategy other than specializing a trait.
#2: does not come for free, it requires significant compiler help to detect
when it is safe to do so.
> N4244 options #2 comes for free, for #1 and #3 you need to work just a
> little
>
#1
new auto ([] { yield 1; })
new(allocator) auto ([] { yield 1; })
These needs a language change not to require a copy/move constructor (which
wouldn't be used anyway due to temporary elision).
#3
struct foo
{
auto gen = [] { yield 1; } ;
};
this requires a language change to allow auto members (which is sorely
missing anyway).
So, not really a lot of work :)
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_6741_623376695.1414594933709
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, October 29, 2014 2:36:36 PM UTC, Gor Nishano=
v 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"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left=
:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-s=
tyle:solid"><div dir=3D"ltr"><div><div>Lastly, the stated position that hav=
ing a stationary frame means that</div><div>we must have heap allocations s=
mells like faulty logic to me. </div></div></div></blockquote><div><br></di=
v><div>I agree with you. You can get stationary coroutine frame in at least=
three ways:</div><div><br></div><div>1. use an allocator to dynamically se=
lect the place where coroutine frame will live: could be on the heap, in th=
e global or on the stack, depending on the allocator</div><div>2. on the st=
ack or another coroutine frame, when coroutine lifetime is fully contained =
within the lifetime of its caller</div><div>3. embedded into another object=
</div><div><br></div><div>N4134 options #1 and #2 comes for free, for =
#3 you have to work to make it happen (muck around with allocators)</div></=
div></blockquote><div><br>#1: the current allocator support relies on the g=
enerator result type and parameters. The decision to which allocator (and w=
hether to use one) should not be statically keyed to the signature. Also no=
t knowing the size of the buffer at compile time prevent some optimizations=
.. Neither of these problems are of course unsurmountable, but I would look =
for a different customization strategy other than specializing a trait. <br=
><br>#2: does not come for free, it requires significant compiler help to d=
etect when it is safe to do so.<br> </div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr"><div>N4244 options #2 comes for free, for=
#1 and #3 you need to work just a little</div></div></blockquote><div><br>=
#1<br>new auto ([] { yield 1; })<br>new(allocator) auto ([] { yield 1; })<b=
r><br>These needs a language change not to require a copy/move constructor =
(which wouldn't be used anyway due to temporary elision).<br><br>#3<br>stru=
ct foo <br>{<br> auto gen =3D [] { yield 1; } ; <br>};<br><br>t=
his requires a language change to allow auto members (which is sorely missi=
ng anyway).<br> <br>So, not really a lot of work :)</div><br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_6741_623376695.1414594933709--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Wed, 29 Oct 2014 10:58:47 -0700 (PDT)
Raw View
------=_Part_5438_604056315.1414605527923
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 29, 2014 8:02:13 AM UTC-7, Giovanni Piero Deretta
wrote:
>
> #1: the current allocator support relies on the generator result type and
> parameters. The decision to which allocator (and whether to use one) should
> not be statically keyed to the signature. Also not knowing the size of the
> buffer at compile time prevent some optimizations. Neither of these
> problems are of course unsurmountable, but I would look for a different
> customization strategy other than specializing a trait.
>
But is that any different as anywhere else in the STL, you either hardcode
it in a type: vector<int, allocator> or you can use a stateful allocator
that you can pass as a parameter:
vector<int, Alloc> v(stateful), or you can use polymorphic allocator,
vector<int, PolyAlloc> v(OmgVirtualFuncsPolymorphicAllocator); :-)
> #2: does not come for free, it requires significant compiler help to
> detect when it is safe to do so.
>
We are language designers, not a compiler writer trade union :-). And I am
on compiler team, so, I guess, my desire of a nice syntax overcomes my
laziness when it comes to making sure that coroutines are pretty and
zero-overhead abstractions. I don't want to decide on one or the other. I
want both.
> So, not really a lot of work :)
>
As I said "a little work", even less work with the other language changes
you suggested.
Cheers,
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5438_604056315.1414605527923
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, October 29, 2014 8:02:13 AM UTC-7, G=
iovanni Piero Deretta wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, =
204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><=
div>#1: the current allocator support relies on the generator result type a=
nd parameters. The decision to which allocator (and whether to use one) sho=
uld not be statically keyed to the signature. Also not knowing the size of =
the buffer at compile time prevent some optimizations. Neither of these pro=
blems are of course unsurmountable, but I would look for a different custom=
ization strategy other than specializing a trait. <br></div></div></blockqu=
ote><div><br></div><div>But is that any different as anywhere else in the S=
TL, you either hardcode it in a type: vector<int, allocator>&nbs=
p;or you can use a stateful allocator that you can pass as a parameter=
: </div><div>vector<int, Alloc> v(stateful), or you can use polymorph=
ic allocator, vector<int, PolyAlloc> v(OmgVirtualFuncsPolymorphicAllo=
cator); :-)</div><div> </div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rg=
b(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div d=
ir=3D"ltr"><div>#2: does not come for free, it requires significant compile=
r help to detect when it is safe to do so.<br></div></div></blockquote><div=
><br></div><div>We are language designers, not a compiler writer trade unio=
n :-). And I am on compiler team, so, I guess, my desire of a nice syn=
tax overcomes my laziness when it comes to making sure that coroutines are =
pretty and zero-overhead abstractions. I don't want to decide on one or the=
other. I want both.</div><div> </div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color:=
rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><di=
v dir=3D"ltr"><div> So, not really a lot of work :)<br></div></div></b=
lockquote><div><br></div><div>As I said "a little work", even less work wit=
h the other language changes you suggested. </div><div><br><=
/div><div>Cheers,</div><div>Gor</div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5438_604056315.1414605527923--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Wed, 29 Oct 2014 11:22:22 -0700 (PDT)
Raw View
------=_Part_725_1841699258.1414606942475
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 29, 2014 5:58:48 PM UTC, Gor Nishanov wrote:
>
>
>>
>> #2: does not come for free, it requires significant compiler help to
>> detect when it is safe to do so.
>>
>
> We are language designers, not a compiler writer trade union :-). And I am
> on compiler team, so, I guess, my desire of a nice syntax overcomes my
> laziness when it comes to making sure that coroutines are pretty and
> zero-overhead abstractions. I don't want to decide on one or the other. I
> want both.
>
:) . So, what magic does the compiler use to optimise this:
generator<int> foo() { while (true) yield 1; }
generator<int> bar() { while (true) yield 0; }
// baz is defined in a separate library
void baz(generator<int>& x);
void baq()
{
auto x = foo();
// baz(x); // this triggers heap allocation and prevents inlining
for (v : x)
std::cerr << v << '\n';
}
This example is even more evil:
struct Base
{
int lastValue = 0;
const int& get() { return lastValue; }
};
struct Generator : Base
{
generator<int> x = foo();
bool next()
{
value = x();
return x;
}
};
// consume is defined in a separate library
void consume(const int& x);
void baq()
{
Generator g;
while (g.next())
consume(g.get());
}
So, can a compiler optimize the above cases whiout seeing the whole
program? If yes, how? Consider these definition of consume and baz...
void consume(const int& x)
{
// All these conversions are well defined
auto& y =
static_cast<Generator&>(reinterpret_cast<Base&>(const_cast<int&>(x))_;
baz(y)
}
void baz(generator<int>& x)
{
auto y = bar();
std::swap(x, y);
}
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_725_1841699258.1414606942475
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, October 29, 2014 5:58:48 PM UTC, Gor=
Nishanov 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"lt=
r"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px=
;border-left-style:solid"><div dir=3D"ltr"><div>#2: does not come for free,=
it requires significant compiler help to detect when it is safe to do so.<=
br></div></div></blockquote><div><br></div><div>We are language designers, =
not a compiler writer trade union :-). And I am on compiler team, so, I gue=
ss, my desire of a nice syntax overcomes my laziness when it comes to =
making sure that coroutines are pretty and zero-overhead abstractions. I do=
n't want to decide on one or the other. I want both.</div></div></blockquot=
e><div><br>:) . So, what magic does the compiler use to optimise this:</div=
><br><br>generator<int> foo() { while (true) yield 1; }<br><br>genera=
tor<int> bar() { while (true) yield 0; }<br><br>// baz is defined in =
a separate library<br>void baz(generator<int>& x);<br><br><br><br=
>void baq()<br>{<br> auto x =3D f=
oo();<br><br> // baz(x); &nb=
sp; // this triggers heap allocation and prevents inlining<br> &=
nbsp; for (v : x) <br>  =
; std::cerr <=
;< v << '\n';<br><br>}<br><br>This example is even more evil:<br><=
br>struct Base<br>{<br> int lastV=
alue =3D 0;<br><br> const int&=
; get() { return lastValue; }<br>};<br><br>struct Generator : Base<br>{<br>=
generator<int> x =3D foo()=
;<br> <br>  =
; bool next()<br> &nbs=
p; {<br> &=
nbsp; value =3D x();<br> &nb=
sp; return x;<br>&nbs=
p; }<br>};<br><br>// consume is defined=
in a separate library<br>void consume(const int& x);<br><br>void baq()=
<br>{<br> Generator g;<br><br>&nb=
sp; while (g.next()) <br> &n=
bsp;  =
; consume(g.get());<br> &nbs=
p; <br>}<br><br>So, can a compiler opti=
mize the above cases whiout seeing the whole program? If yes, how? Consider=
these definition of consume and baz...<br><br><br>void consume(const int&a=
mp; x)<br>{<br> // All these conv=
ersions are well defined<br> auto=
& y =3D static_cast<Generator&>(reinterpret_cast<Base&=
>(const_cast<int&>(x))_;<br> &nbs=
p; baz(y)<br>}<br><br><br>void baz(generator<int>& x)<br>{<=
br> auto y =3D bar();<br> &n=
bsp; std::swap(x, y);<br>}<br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_725_1841699258.1414606942475--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Wed, 29 Oct 2014 16:22:17 -0700 (PDT)
Raw View
------=_Part_75_552704443.1414624938047
Content-Type: text/plain; charset=UTF-8
>
> :) . So, what magic does the compiler use to optimise this:
>
>
> generator<int> foo() { while (true) yield 1; }
>
> generator<int> bar() { while (true) yield 0; }
>
> // baz is defined in a separate library
> void baz(generator<int>& x);
>
> void baq()
> {
> auto x = foo();
>
gor: __foo_frame $tmp; // note: coroutine frame != coroutine
gor: auto x = __foo_impl($tmp); // x = generator, frame points at $tmp
which is a local temporary in baq
>
> // baz(x); // this triggers heap allocation and prevents inlining
>
gor: // why should this any allocations, baz takes
generator by reference
> for (v : x)
> std::cerr << v << '\n';
> }
>
> This example is even more evil:
>
Note that any attempt to do heap elision optimization in your example will
result in equivalent of returning address of a local from a function that
already went off the stack.
This is a leak / crash / buffer overrun waiting to happen.
Also, you can just teach resumable function deal directly with your
Generator type and then heap elision will apply.
I believe that for is that for any given problem, there is a solution in
which both 4244 and 4134 have identical number of allocations and
performance.
Gor
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_75_552704443.1414624938047
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div>:) . So=
, what magic does the compiler use to optimise this:</div><br><br>generator=
<int> foo() { while (true) yield 1; }<br><br>generator<int> bar=
() { while (true) yield 0; }<br><br>// baz is defined in a separate library=
<br>void baz(generator<int>& x);<br><br>void baq()<br>{<br> =
auto x =3D foo();<br></div></blockquot=
e><div>gor: __foo_frame $tmp;  =
;// note: coroutine frame !=3D coroutine </div><div>gor: &n=
bsp; auto x =3D __foo_impl($tmp); // x =3D generator, frame points at=
$tmp which is a local temporary in baq </div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-col=
or: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">=
<div dir=3D"ltr"><br> // baz(x);&=
nbsp; // this triggers heap allocation and prevents inlining<br></div=
></blockquote><div>gor: &nbs=
p; &=
nbsp; // why should this any allocations, baz takes generator by reference<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; =
padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width=
: 1px; border-left-style: solid;"><div dir=3D"ltr"> =
for (v : x) <br> &nbs=
p; std::cerr << v <=
;< '\n';<br>}<br><br>This example is even more evil:<br></div></blockquo=
te><div><br></div><div>Note that any attempt to do heap elision optimizatio=
n in your example will result in equivalent of returning address of a =
local from a function that already went off the stack.</div><div>This is a =
leak / crash / buffer overrun waiting to happen. </div><div><br></div>=
<div>Also, you can just teach resumable function deal directly with your Ge=
nerator type and then heap elision will apply.</div><div><br></div><div>I b=
elieve that for is that for any given problem, there is a solution in =
which both 4244 and 4134 have identical number of allocations and performan=
ce. </div><div><br></div><div>Gor</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_75_552704443.1414624938047--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Thu, 30 Oct 2014 01:03:36 -0700 (PDT)
Raw View
------=_Part_301_1130153362.1414656216523
Content-Type: text/plain; charset=UTF-8
On Wednesday, October 29, 2014 11:22:18 PM UTC, Gor Nishanov wrote:
>
> :) . So, what magic does the compiler use to optimise this:
>>
>>
>> generator<int> foo() { while (true) yield 1; }
>>
>> generator<int> bar() { while (true) yield 0; }
>>
>> // baz is defined in a separate library
>> void baz(generator<int>& x);
>>
>> void baq()
>> {
>> auto x = foo();
>>
> gor: __foo_frame $tmp; // note: coroutine frame != coroutine
> gor: auto x = __foo_impl($tmp); // x = generator, frame points at $tmp
> which is a local temporary in baq
>
That's not safe. 'baz' will swap the generator away taking ownership of the
frame. It could persist beyond the scope of 'baq'
>
>> // baz(x); // this triggers heap allocation and prevents
>> inlining
>>
> gor: // why should this any allocations, baz takes
> generator by reference
>
because the compiler will be prevented to perform the optimization.
> for (v : x)
>> std::cerr << v << '\n';
>> }
>>
>> This example is even more evil:
>>
>
> Note that any attempt to do heap elision optimization in your example will
> result in equivalent of returning address of a local from a function that
> already went off the stack.
> This is a leak / crash / buffer overrun waiting to happen.
>
Unless generator<T> has unspecified and surprising semantics[1], no, it is
not the same, In the examples I'm swapping the generator of 'baz' with
another generator with a different lifetime. It is a perfectly safe thing
to do (for example if you substitute the generator<> with string, vector,
function, etc); are claiming that my examples invoke UB? If so, where
exactly?
[1] You really only have three options: the generator is non copyable/non
movable (which does not match the examples in the paper), non movable
(which also doesn't match the examples, but is a reasonable thing to do for
a resource owning handle) or copyable (with shallow copy semantics and
reference counting, which make it not a regular type). My examples assume
that the generator is at least moveable.
-- gpd
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_301_1130153362.1414656216523
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, October 29, 2014 11:22:18 PM UTC, Gor Nishan=
ov 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"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-lef=
t:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-=
style:solid"><div dir=3D"ltr"><div>:) . So, what magic does the compiler us=
e to optimise this:</div><br><br>generator<int> foo() { while (true) =
yield 1; }<br><br>generator<int> bar() { while (true) yield 0; }<br><=
br>// baz is defined in a separate library<br>void baz(generator<int>=
& x);<br><br>void baq()<br>{<br> &nb=
sp; auto x =3D foo();<br></div></blockquote><div>gor: &nbs=
p; __foo_frame $tmp; // note: coroutine frame !=3D co=
routine </div><div>gor: auto x =3D __foo_impl(=
$tmp); // x =3D generator, frame points at $tmp which is a local temporary =
in baq </div></div></blockquote><div><br>That's not safe. 'baz' will swap t=
he generator away taking ownership of the frame. It could persist beyond th=
e scope of 'baq'<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"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left=
-width:1px;border-left-style:solid"><div dir=3D"ltr"><br> =
// baz(x); // this triggers heap alloc=
ation and prevents inlining<br></div></blockquote><div>gor: &nbs=
p; &=
nbsp; // why should this any allocation=
s, baz takes generator by reference</div></div></blockquote><div><br>becaus=
e the compiler will be prevented to perform the optimization.<br> </di=
v><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"><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;b=
order-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:s=
olid"><div dir=3D"ltr"> for (v : =
x) <br> &n=
bsp; std::cerr << v << '\n';<br>}<br><br>This=
example is even more evil:<br></div></blockquote><div><br></div><div>Note =
that any attempt to do heap elision optimization in your example will resul=
t in equivalent of returning address of a local from a function that a=
lready went off the stack.</div><div>This is a leak / crash / buffer o=
verrun waiting to happen. </div></div></blockquote><div><br>Unless generato=
r<T> has unspecified and surprising semantics[1], no, it is not the s=
ame, In the examples I'm swapping the generator of 'baz' with another=
generator with a different lifetime. It is a perfectly safe thing to do (f=
or example if you substitute the generator<> with string, vector, fun=
ction, etc); are claiming that my examples invoke UB? If so, where exactly?=
<br><br>[1] You really only have three options: the generator is non copyab=
le/non movable (which does not match the examples in the paper), non movabl=
e (which also doesn't match the examples, but is a reasonable thing to do f=
or a resource owning handle) or copyable (with shallow copy semantics and r=
eference counting, which make it not a regular type). My examples assume th=
at the generator is at least moveable.<br><br><br></div>-- gpd<br></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_301_1130153362.1414656216523--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Thu, 30 Oct 2014 06:09:58 -0700 (PDT)
Raw View
------=_Part_648_185979136.1414674598976
Content-Type: text/plain; charset=UTF-8
You are right. Passing generator by reference to a function that you cannot
see into the body, should inhibit this optimization.
Since lifetime can be stolen via move.
>> Unless generator<T> has unspecified and surprising semantics[1], no, it
is not the same, In the examples I'm swapping the generator of 'baz' with
another generator with a different lifetime.
What I meant is that applying heap elision optimization is unsafe and thus
should not happen in this example.
Sure, generator is movable. Coroutine state is not. Therefore, if move
happens or you cannot prove that it cannot happen as in you baz() example.
Coroutine Frame Allocation Elision Optimization (CFAEO :-)) should be
inhibited.
--
---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_648_185979136.1414674598976
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>You are right. Passing generator by reference to a fu=
nction that you cannot see into the body, should inhibit this optimization.=
</div><div>Since lifetime can be stolen via move.</div><div><br></div><div>=
>> Unless generator<T> has unspecified and surprising semantics=
[1], no, it is not the same, In the examples I'm swapping the generator of =
'baz' with another generator with a different lifetime. </div><div><b=
r></div><div>What I meant is that applying heap elision optimization is uns=
afe and thus should not happen in this example.</div><div><br></div><div>Su=
re, generator is movable. Coroutine state is not. Therefore, if move happen=
s or you cannot prove that it cannot happen as in you baz() example. Corout=
ine Frame Allocation Elision Optimization (CFAEO :-)) should be inhibited.<=
br></div></div>
<p></p>
-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_648_185979136.1414674598976--
.