Topic: Questions on N3857 "Improvements to std::future<T>
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Tue, 8 Sep 2015 01:35:29 -0700 (PDT)
Raw View
------=_Part_5379_1211945999.1441701329195
Content-Type: multipart/alternative;
boundary="----=_Part_5380_197164835.1441701329196"
------=_Part_5380_197164835.1441701329196
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I keep finding newer and newer versions of this paper! If there's one out=
=20
there which is newer than N3857=20
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3857.pdf> (which=
=20
supersedes N3784, which superseded N3721, which superseded N3634, which=20
superseded N3558, which superseded N3428), please let me know. :)
I have at least three questions. #2 is the most important to me right now.
*(1)* In many places, N3857 talks about futures being "copied." This is=20
just a colloquialism for "moved," right, since normal (non-shared) futures=
=20
aren't copyable?
For example, page 13
1.=20
=20
Returns: An object of type future<decltype(func(*this))> that refers to=
=20
the shared state created by the continuation.=20
=20
where func(*this) invokes a deleted copy constructor; or page 16
-=20
=20
Each future and shared_future is waited upon and then copied *[sic]*=20
into the collection of the=20
=20
output (returned) future, maintaining the order of the futures in the=20
input collection.=20
=20
(and pages 17 and 18 similarly).
*(2)* What should be the result of
std::future<std::tuple<>> f =3D std::when_any(); // call the=20
variadic-template version with zero arguments
assert(f.valid()); // yes?
assert(not f.ready()); // yes... or no?
f.get(); // blocks forever... or throws std::broken_promise? ...or=20
something else?
The same question applies if you call the InputIterator version with a=20
range of length zero.
I would naturally assume that the future f would only ever become ready if=
=20
"at least one" of the N=3D0 provided futures became ready; which is to say,=
=20
it would never become ready, and f.get() would block forever.
However, it seems that Folly::collectAny() does not implement this natural=
=20
behavior; instead, it produces the equivalent of=20
std::make_exceptional_future(broken_promise) =E2=80=94 because it's impleme=
nted in=20
terms of a promise stored in a shared state that is kept alive by N=20
shared_ptrs, so that when N=3D0, the promise dies immediately without havin=
g=20
been fulfilled.
To further confuse matters, N4313 (the current draft of the Concurrency TS,=
=20
if I understand correctly?) explicitly specifies that std::when_any() with=
=20
N=3D0 should return a future *which is ready and holds a value!*
https://raw.githubusercontent.com/cplusplus/concurrency_ts/master/N4313_fut=
ure.html
This matches the behavior of boost::when_any, as far as I can tell.
http://melpon.org/wandbox/permlink/oj2DHNRXGyVNUpME
I can't see any rationale for this behavior, except perhaps ease of=20
implementation =E2=80=94 it's easy to implement make_ready_future() in term=
s of=20
C++14 primitives, but I'm not aware of any easy way to implement=20
"make_never_ready_future()" that doesn't involve hacking on the internals=
=20
of future itself.
The same question applies to std::when_n, whenever *that* gets proposed:=20
what should be the result of std::when_n(10, f, g, h)? A future that=20
becomes ready only when 10 of the 3 inputs have been satisfied, or a future=
=20
that becomes ready as soon as *all* 3 of the inputs have been satisfied?
*(3)* Incidentally, what's the history behind *is_ready()*'s name change?=
=20
N3634 (2013-05-02) still had it as ready(), but by N3721 (2013-08-30, after=
=20
Chicago) it had somehow changed to is_ready(). The new name seems=20
inconsistent with all the existing STL "adjective" accessors =E2=80=94 empt=
y(),=20
good(), bad(), valid(), etc.
Thanks,
=E2=80=93Arthur
--=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_5380_197164835.1441701329196
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I keep finding newer and newer versions of this paper! If =
there's one out there which is newer than <a href=3D"http://www.open-st=
d.org/jtc1/sc22/wg21/docs/papers/2014/n3857.pdf">N3857</a> (which supersede=
s N3784, which superseded N3721, which superseded N3634, which superseded N=
3558, which superseded N3428), please let me know. :)<div><br></div><div>I =
have at least three questions. #2 is the most important to me right now.</d=
iv><div><br></div><div><br></div><div><b>(1)</b> In many places, N3857 talk=
s about futures being "copied." This is just a colloquialism for =
"moved," right, since normal (non-shared) futures aren't copy=
able?</div><div>For example, page 13</div><div>
=09
=09
=09
<div class=3D"page" title=3D"Page 13">
<div class=3D"layoutArea">
<div class=3D"column">
<ol start=3D"0" style=3D"list-style-type: none">
<li>
<p><span style=3D"font-size: 11.000000pt; font-family: 'Calibri,=
Italic'">Returns: </span><span style=3D"font-size: 11.000000pt; font-fa=
mily: 'Calibri'">An object of type </span><span style=3D"font-size:=
9.000000pt; font-family: 'Consolas,Bold'">future<decltype(func(=
*this))> </span><span style=3D"font-size: 11.000000pt; font-family: '=
;Calibri'">that refers to the shared state created by
the continuation.=C2=A0</span></p>
</li>
=09
</ol></div>
</div>
</div></div><div>where=C2=A0<span style=3D"font-family: 'Consolas,Bol=
d'; font-size: 12px; line-height: 17px;">func(*this)</span>=C2=A0invoke=
s a deleted copy constructor; or page 16</div><div>
=09
=09
=09
<div class=3D"page" title=3D"Page 16">
<div class=3D"layoutArea">
<div class=3D"column">
<ul style=3D"list-style-type: none">
<li>
<p><span style=3D"font-size: 11.000000pt; font-family: 'Calibri&=
#39;">Each </span><span style=3D"font-size: 9.000000pt; font-family: 'C=
onsolas,Bold'">future </span><span style=3D"font-size: 11.000000pt; fon=
t-family: 'Calibri'">and </span><span style=3D"font-size: 9.000000p=
t; font-family: 'Consolas,Bold'">shared_future </span><span style=
=3D"font-size: 11.000000pt; font-family: 'Calibri'">is waited upon =
and then copied <i>[sic]</i> into the collection of the
</span></p>
<p><span style=3D"font-size: 11.000000pt; font-family: 'Calibri&=
#39;">output (returned) future, maintaining the order of the futures in the=
input collection.</span><span style=3D"font-family: Calibri; font-size: 11=
pt;">=C2=A0</span></p>
</li>
</ul>
</div>
</div>
</div></div><div>(and pages 17 and 18 similarly).<br></div><div><br></div=
><div><br></div><div><b>(2)</b> What should be the result of</div><div><br>=
</div><div><font face=3D"courier new, monospace">=C2=A0 =C2=A0 std::future&=
lt;std::tuple<>> f =3D std::when_any(); =C2=A0// call the variadic=
-template version with zero arguments</font></div><div><font face=3D"courie=
r new, monospace">=C2=A0 =C2=A0 assert(f.valid()); =C2=A0// yes?</font></di=
v><div><font face=3D"courier new, monospace">=C2=A0 =C2=A0 assert(not f.rea=
dy()); =C2=A0// yes... or no?</font></div><div><font face=3D"courier new, m=
onospace">=C2=A0 =C2=A0 f.get(); =C2=A0// blocks forever... or throws std::=
broken_promise? ...or something else?</font></div><div><br></div><div>The s=
ame question applies if you call the InputIterator version with a range of =
length zero.</div><div>I would naturally assume that the future f would onl=
y ever become ready if "at least one" of the N=3D0 provided futur=
es became ready; which is to say, it would never become ready, and f.get() =
would block forever.</div><div>However, it seems that Folly::collectAny() d=
oes not implement this natural behavior; instead, it produces the equivalen=
t of std::make_exceptional_future(broken_promise) =E2=80=94 because it'=
s implemented in terms of a promise stored in a shared state that is kept a=
live by N shared_ptrs, so that when N=3D0, the promise dies immediately wit=
hout having been fulfilled.</div><div><br></div><div>To further confuse mat=
ters, N4313 (the current draft of the Concurrency TS, if I understand corre=
ctly?) explicitly specifies that <font face=3D"courier new, monospace">std:=
:when_any()</font> with N=3D0 should return a future <i><b>which is ready a=
nd holds a value!</b></i></div><div><a href=3D"https://raw.githubuserconten=
t.com/cplusplus/concurrency_ts/master/N4313_future.html">https://raw.github=
usercontent.com/cplusplus/concurrency_ts/master/N4313_future.html<br></a></=
div><div>This matches the behavior of boost::when_any, as far as I can tell=
..</div><div><a href=3D"http://melpon.org/wandbox/permlink/oj2DHNRXGyVNUpME"=
>http://melpon.org/wandbox/permlink/oj2DHNRXGyVNUpME<br></a></div><div>I ca=
n't see any rationale for this behavior, except perhaps ease of impleme=
ntation =E2=80=94 it's easy to implement make_ready_future() in terms o=
f C++14 primitives, but I'm not aware of any easy way to implement &quo=
t;make_never_ready_future()" that doesn't involve hacking on the i=
nternals of <font face=3D"courier new, monospace">future</font> itself.</di=
v><div><br></div><div>The same question applies to <font face=3D"courier ne=
w, monospace">std::when_n</font>, whenever <i>that</i> gets proposed: what =
should be the result of <font face=3D"courier new, monospace">std::when_n(1=
0, f, g, h)</font>? A future that becomes ready only when 10 of the 3 input=
s have been satisfied, or a future that becomes ready as soon as <i>all</i>=
=C2=A03 of the inputs have been satisfied?</div><div><br></div><div><br></d=
iv><div><b>(3)</b> Incidentally, what's the history behind <b><font fac=
e=3D"courier new, monospace">is_ready()</font></b>'s name change? N3634=
(2013-05-02) still had it as <font face=3D"courier new, monospace">ready()=
</font>, but by N3721 (2013-08-30, after Chicago) it had somehow changed to=
<font face=3D"courier new, monospace">is_ready()</font>. The new name seem=
s inconsistent with all the existing STL "adjective" accessors =
=E2=80=94 empty(), good(), bad(), valid(), etc.</div><div><br></div><div><b=
r></div><div>Thanks,</div><div>=E2=80=93Arthur</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_5380_197164835.1441701329196--
------=_Part_5379_1211945999.1441701329195--
.