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&#39;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 &quot;copied.&quot; This is just a colloquialism for =
&quot;moved,&quot; right, since normal (non-shared) futures aren&#39;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: &#39;Calibri,=
Italic&#39;">Returns: </span><span style=3D"font-size: 11.000000pt; font-fa=
mily: &#39;Calibri&#39;">An object of type </span><span style=3D"font-size:=
 9.000000pt; font-family: &#39;Consolas,Bold&#39;">future&lt;decltype(func(=
*this))&gt; </span><span style=3D"font-size: 11.000000pt; font-family: &#39=
;Calibri&#39;">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: &#39;Consolas,Bol=
d&#39;; 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: &#39;Calibri&=
#39;">Each </span><span style=3D"font-size: 9.000000pt; font-family: &#39;C=
onsolas,Bold&#39;">future </span><span style=3D"font-size: 11.000000pt; fon=
t-family: &#39;Calibri&#39;">and </span><span style=3D"font-size: 9.000000p=
t; font-family: &#39;Consolas,Bold&#39;">shared_future </span><span style=
=3D"font-size: 11.000000pt; font-family: &#39;Calibri&#39;">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: &#39;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&lt;&gt;&gt; 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 &quot;at least one&quot; 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&#39;=
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&#39;t see any rationale for this behavior, except perhaps ease of impleme=
ntation =E2=80=94 it&#39;s easy to implement make_ready_future() in terms o=
f C++14 primitives, but I&#39;m not aware of any easy way to implement &quo=
t;make_never_ready_future()&quot; that doesn&#39;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&#39;s the history behind <b><font fac=
e=3D"courier new, monospace">is_ready()</font></b>&#39;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 &quot;adjective&quot; 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&quot; 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--

.