Topic: Comments on resumable functions [N4402/N4403]


Author: Shahms King <shahms.king@gmail.com>
Date: Mon, 04 May 2015 18:30:01 +0000
Raw View
--001a1141b7e8080a63051545c08f
Content-Type: text/plain; charset=UTF-8

Thanks for publishing the update, it solves a number of the complications
with the earlier versions and also clarifies some of my misunderstandings.
In fact, the specific mention of the potential problems with await and
non-eventually returning resumable functions led me notice a similar
problem with non-suspendable "immediately returning" promise types (such as
a hypothetical one for expected<T, E>).

Fundamentally, I think there are 4 different promise types:

   1.

   non-resumable / immediately returning (expected<T, E>)
   1.

      set_result
      2.

      lacks {initial,final}_suspend? (currently unspecified)
      2.

   internally-resumable / eventually returning (future<T>)
   1.

      set_result
      3.

   externally-resumable (generator<T>)
   1.

      yield_value
      4.

   mutually-resumable / eventually returning (async_generator<T>)
   1.

      yield_value
      2. set_result


The key point is where it is *safe* to call resume(). You've resolved this
my making it illegal to call `await` from within an externally-resumable
function (because it is unsafe to call resume() from within such a
function) and illegal to call `yield` from within an internally-resumable
function (because the promise lacks yield_from(), but it is also unsafe to
call resume() from *outside* such a function).

Unfortunately, given the current specification it is either impossible or
excessively complicated to safely implement await for a non-resumable type
such as `expected<T, E>` due to the possibility of (unexpectedly)
suspending execution, e.g.

expected<T, E> foo() {
  T1 t = await UnwrapExpected();
  F f = await ReturnsAFuture();  // Ooops! Unexpected suspend & early
return!
  return transform(t);
}

I think the internal-vs-externally resumable dichotomy is sufficient to
justify two separate types: resumable_handle<P>, which represents the
entire resumable function; and suspension_handle<P>, which represents a
single suspension-point within the function.  From here, we can specialize
the handle based on the promise type to ensure resume is only present on
the handle(s) which can safely be resumed.  This is slightly complicated by
the import/export mechanism, but could be resolved by predicating
conversion and export operations on the presence of resume() on the handle,
e.g.

struct cancellable_handle {

 // 18.11.2.1 construct/reset

 cancellable_handle() noexcept;

 cancellable_handle(std::nullptr_t) noexcept;

 cancellable_handle& operator=(nullptr_t) noexcept;

 // 18.11.2.3 capacity

 explicit operator bool() const noexcept;

 // {cancellation}

 void destroy() const;

};

template <>

struct resumable_handle<void> : cancellable_handle {

 // 18.11.2.1 construct/reset

 using cancellable_handle::cancellable_handle;

 resumable_handle& operator=(nullptr_t) noexcept;

 // 18.11.2.2 export/import

 static resumable_handle from_address(void* addr) noexcept;

 void* to_address() const noexcept;

  // 18.11.2.4 resumption

 void operator()() const;

 void resume() const;

 // 18.11.2.5 completion check

 bool done() const noexcept;

};

template <>

struct resumable_handle<ExternallyResumable<P>> : resumable_handle<> {

 // 18.11.2.1 construct/reset

 using resumable_handle<>::resumable_handle;

 resumable_handle& operator=(nullptr_t) noexcept;

 // 18.11.2.6 export/import

 static resumable_handle from_promise(Promise*) noexcept;

 Promise& promise() noexcept;

 Promise const& promise() const noexcept;

};

template <>

struct resumable_handle<InternallyResumable<P>> : cancellable_handle {

 ...

};


You end up with a similar implementation for suspension_handle<>.
Additionally, it seems like you could greatly reduce the need for
from_promise() by having get_return_object(resumable_handle<P>), rather
than the void argument list.  Ultimately, supporting non-suspendable types
(optional<T>, expected<T, E>, etc.) may be deemed out of scope, but I still
feel that using different types for the resumable_handle and
suspension_handle (or await_handle) would allow such a change to be made
compatibly at a later date.

Thanks,
--Shahms

--

---
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/.

--001a1141b7e8080a63051545c08f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Thanks for publishing the update, it solves a number of th=
e complications with the earlier versions and also clarifies some of my mis=
understandings.=C2=A0 In fact, the specific mention of the potential proble=
ms with await and non-eventually returning resumable functions led me notic=
e a similar problem with non-suspendable &quot;immediately returning&quot; =
promise types (such as a hypothetical one for expected&lt;T, E&gt;).<div><b=
r></div><div>Fundamentally, I think there are 4 different promise types:</d=
iv><div><span id=3D"docs-internal-guid-73772495-200b-982d-5c27-42f195c2e89a=
"><ol style=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"l=
ist-style-type:lower-alpha;font-size:15px;font-family:Arial;color:rgb(0,0,0=
);vertical-align:baseline;background-color:transparent"><p dir=3D"ltr" styl=
e=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vert=
ical-align:baseline;white-space:pre-wrap;background-color:transparent">non-=
resumable / immediately returning (expected&lt;T, E&gt;)</span></p></li><ol=
 style=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list-s=
tyle-type:lower-roman;font-size:15px;font-family:Arial;color:rgb(0,0,0);ver=
tical-align:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"=
line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-=
align:baseline;white-space:pre-wrap;background-color:transparent">set_resul=
t</span></p></li><li dir=3D"ltr" style=3D"list-style-type:lower-roman;font-=
size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;backgr=
ound-color:transparent"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top=
:0pt;margin-bottom:0pt"><span style=3D"vertical-align:baseline;white-space:=
pre-wrap;background-color:transparent">lacks {initial,final}_suspend? (curr=
ently unspecified)</span></p></li></ol><li dir=3D"ltr" style=3D"list-style-=
type:lower-alpha;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical=
-align:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"line-=
height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent">internally-res=
umable / eventually returning (future&lt;T&gt;)</span></p></li><ol style=3D=
"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list-style-type=
:lower-roman;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-ali=
gn:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"line-heig=
ht:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align:bas=
eline;white-space:pre-wrap;background-color:transparent">set_result</span><=
/p></li></ol><li dir=3D"ltr" style=3D"list-style-type:lower-alpha;font-size=
:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;background=
-color:transparent"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt=
;margin-bottom:0pt"><span style=3D"vertical-align:baseline;white-space:pre-=
wrap;background-color:transparent">externally-resumable (generator&lt;T&gt;=
)</span></p></li><ol style=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"=
ltr" style=3D"list-style-type:lower-roman;font-size:15px;font-family:Arial;=
color:rgb(0,0,0);vertical-align:baseline;background-color:transparent"><p d=
ir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><spa=
n style=3D"vertical-align:baseline;white-space:pre-wrap;background-color:tr=
ansparent">yield_value</span></p></li></ol><li dir=3D"ltr" style=3D"list-st=
yle-type:lower-alpha;font-size:15px;font-family:Arial;color:rgb(0,0,0);vert=
ical-align:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"l=
ine-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-a=
lign:baseline;white-space:pre-wrap;background-color:transparent">mutually-r=
esumable / eventually returning (async_generator&lt;T&gt;)</span></p></li><=
ol style=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list=
-style-type:lower-roman;font-size:15px;font-family:Arial;color:rgb(0,0,0);v=
ertical-align:baseline;background-color:transparent"><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"verti=
cal-align:baseline;white-space:pre-wrap;background-color:transparent">yield=
_value</span></p></li><li dir=3D"ltr" style=3D"list-style-type:lower-roman;=
font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;b=
ackground-color:transparent"><span style=3D"vertical-align:baseline;white-s=
pace:pre-wrap;background-color:transparent">set_result</span></li></ol></ol=
><div><font color=3D"#000000" face=3D"Arial"><span style=3D"font-size:15px;=
white-space:pre-wrap"><br></span></font></div><div>The key point is where i=
t is *safe* to call resume(). You&#39;ve resolved this my making it illegal=
 to call `await` from within an externally-resumable function (because it i=
s unsafe to call resume() from within such a function) and illegal to call =
`yield` from within an internally-resumable function (because the promise l=
acks yield_from(), but it is also unsafe to call resume() from *outside* su=
ch a function).</div><div><br></div><div>Unfortunately, given the current s=
pecification it is either impossible or excessively complicated to safely i=
mplement await for a non-resumable type such as `expected&lt;T, E&gt;` due =
to the possibility of (unexpectedly) suspending execution, e.g.</div><div><=
br></div><div>expected&lt;T, E&gt; foo() {</div><div>=C2=A0 T1 t =3D await =
UnwrapExpected();</div><div>=C2=A0 F f =3D await ReturnsAFuture(); =C2=A0//=
 Ooops! Unexpected suspend &amp; early return!</div><div>=C2=A0 return tran=
sform(t);=C2=A0</div><div>}</div><div><br></div><div>I think the internal-v=
s-externally resumable dichotomy is sufficient to justify two separate type=
s: resumable_handle&lt;P&gt;, which represents the entire resumable functio=
n; and suspension_handle&lt;P&gt;, which represents a single suspension-poi=
nt within the function.=C2=A0 From here, we can specialize the handle based=
 on the promise type to ensure resume is only present on the handle(s) whic=
h can safely be resumed.=C2=A0 This is slightly complicated by the import/e=
xport mechanism, but could be resolved by predicating conversion and export=
 operations on the presence of resume() on the handle, e.g.</div><div><br><=
/div><div><span id=3D"docs-internal-guid-73772495-202b-99a2-a52b-e1f5dc42b6=
9d"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0=
pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:r=
gb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:tra=
nsparent">struct cancellable_handle {</span></p><p dir=3D"ltr" style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15=
px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseli=
ne;white-space:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.1 c=
onstruct/reset</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-to=
p:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Cou=
rier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap=
;background-color:transparent"> =C2=A0cancellable_handle() noexcept;</span>=
</p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0=
pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:r=
gb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:tra=
nsparent"> =C2=A0cancellable_handle(std::nullptr_t) noexcept;</span></p><p =
dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><sp=
an style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,=
0);vertical-align:baseline;white-space:pre-wrap;background-color:transparen=
t"> =C2=A0cancellable_handle&amp; operator=3D(nullptr_t) noexcept;</span></=
p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom=
:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color=
:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:t=
ransparent"> =C2=A0// 18.11.2.3 capacity</span></p><p dir=3D"ltr" style=3D"=
line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size=
:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:bas=
eline;white-space:pre-wrap;background-color:transparent"> =C2=A0explicit op=
erator bool() const noexcept;</span></p><br><p dir=3D"ltr" style=3D"line-he=
ight:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;f=
ont-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;w=
hite-space:pre-wrap;background-color:transparent"> =C2=A0// {cancellation}<=
/span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bo=
ttom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;c=
olor:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-col=
or:transparent"> =C2=A0void destroy() const;</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent">};</span></p><=
br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0p=
t"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rg=
b(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:tran=
sparent">template &lt;&gt;</span></p><p dir=3D"ltr" style=3D"line-height:1.=
38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-fam=
ily:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-sp=
ace:pre-wrap;background-color:transparent">struct resumable_handle&lt;void&=
gt; : cancellable_handle {</span></p><p dir=3D"ltr" style=3D"line-height:1.=
38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-fam=
ily:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-sp=
ace:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.1 construct/re=
set</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margi=
n-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#3=
9;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background=
-color:transparent"> =C2=A0using cancellable_handle::cancellable_handle;</s=
pan></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bott=
om:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;col=
or:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color=
:transparent"> =C2=A0resumable_handle&amp; operator=3D(nullptr_t) noexcept;=
</span></p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;marg=
in-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#=
39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;backgroun=
d-color:transparent"> =C2=A0// 18.11.2.2 export/import</span></p><p dir=3D"=
ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span styl=
e=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vert=
ical-align:baseline;white-space:pre-wrap;background-color:transparent"> =C2=
=A0static resumable_handle from_address(void* addr) noexcept;</span></p><p =
dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><sp=
an style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,=
0);vertical-align:baseline;white-space:pre-wrap;background-color:transparen=
t"> =C2=A0void* to_address() const noexcept;</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent"> </span></p><p=
 dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><s=
pan style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0=
,0);vertical-align:baseline;white-space:pre-wrap;background-color:transpare=
nt"> =C2=A0// 18.11.2.4 resumption</span></p><p dir=3D"ltr" style=3D"line-h=
eight:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;=
font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;=
white-space:pre-wrap;background-color:transparent"> =C2=A0void operator()()=
 const;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier Ne=
w&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;backgr=
ound-color:transparent"> =C2=A0void resume() const;</span></p><br><p dir=3D=
"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span sty=
le=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);ver=
tical-align:baseline;white-space:pre-wrap;background-color:transparent"> =
=C2=A0// 18.11.2.5 completion check</span></p><p dir=3D"ltr" style=3D"line-=
height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px=
;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline=
;white-space:pre-wrap;background-color:transparent"> =C2=A0bool done() cons=
t noexcept;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0=
pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courie=
r New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;ba=
ckground-color:transparent">};</span></p><br><p dir=3D"ltr" style=3D"line-h=
eight:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;=
font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;=
white-space:pre-wrap;background-color:transparent">template &lt;&gt;</span>=
</p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0=
pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:r=
gb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:tra=
nsparent">struct resumable_handle&lt;ExternallyResumable&lt;P&gt;&gt; : res=
umable_handle&lt;&gt; {</span></p><p dir=3D"ltr" style=3D"line-height:1.38;=
margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family=
:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space=
:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.1 construct/reset=
</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-b=
ottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;=
color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-co=
lor:transparent"> =C2=A0using resumable_handle&lt;&gt;::resumable_handle;</=
span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bot=
tom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;co=
lor:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-colo=
r:transparent"> =C2=A0resumable_handle&amp; operator=3D(nullptr_t) noexcept=
;</span></p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;mar=
gin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&=
#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;backgrou=
nd-color:transparent"> =C2=A0// 18.11.2.6 export/import</span></p><p dir=3D=
"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span sty=
le=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);ver=
tical-align:baseline;white-space:pre-wrap;background-color:transparent"> =
=C2=A0static resumable_handle from_promise(Promise*) noexcept;</span></p><p=
 dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><s=
pan style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0=
,0);vertical-align:baseline;white-space:pre-wrap;background-color:transpare=
nt"> =C2=A0Promise&amp; promise() noexcept;</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0Promise=
 const&amp; promise() const noexcept;</span></p><p dir=3D"ltr" style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15=
px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseli=
ne;white-space:pre-wrap;background-color:transparent">};</span></p><br><p d=
ir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><spa=
n style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0=
);vertical-align:baseline;white-space:pre-wrap;background-color:transparent=
">template &lt;&gt;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;marg=
in-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#3=
9;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre=
-wrap;background-color:transparent">struct resumable_handle&lt;InternallyRe=
sumable&lt;P&gt;&gt; : cancellable_handle {</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0...</sp=
an></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-botto=
m:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;colo=
r:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent">};</span></p><div><br></div><div><span style=3D"font-size:15px=
;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline=
;white-space:pre-wrap;background-color:transparent"><br></span></div><div>Y=
ou end up with a similar implementation for suspension_handle&lt;&gt;.=C2=
=A0 Additionally, it seems like you could greatly reduce the need for from_=
promise() by having get_return_object(resumable_handle&lt;P&gt;), rather th=
an the void argument list.=C2=A0 Ultimately, supporting non-suspendable typ=
es (optional&lt;T&gt;, expected&lt;T, E&gt;, etc.) may be deemed out of sco=
pe, but I still feel that using different types for the resumable_handle an=
d suspension_handle (or await_handle) would allow such a change to be made =
compatibly at a later date.</div><div><br></div><div>Thanks,</div><div>--Sh=
ahms</div></span></div><div><br></div></span></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 />

--001a1141b7e8080a63051545c08f--

.


Author: Shahms King <shahms.king@gmail.com>
Date: Wed, 13 May 2015 15:53:53 +0000
Raw View
--089e011772673149970515f89ec1
Content-Type: text/plain; charset=UTF-8

Hey, Gor, I'm not sure if you've had a chance to see my earlier comments
yet or not.  My primary concern is with enabling zero-overhead unwrapping
APIs.  Even if it's decided to be not worth the effort to do so with the
current proposal, it would be nice to at least enable a future proposal to
do so in a backwards-compatible fashion.  I think splitting the handle
types accomplishes that, but may be missing some reason for keeping them
the same (or at least leaving a path open for converting between the two).

Thanks,
--Shahms

On Mon, May 4, 2015 at 11:30 AM Shahms King <shahms.king@gmail.com> wrote:

> Thanks for publishing the update, it solves a number of the complications
> with the earlier versions and also clarifies some of my misunderstandings.
> In fact, the specific mention of the potential problems with await and
> non-eventually returning resumable functions led me notice a similar
> problem with non-suspendable "immediately returning" promise types (such as
> a hypothetical one for expected<T, E>).
>
> Fundamentally, I think there are 4 different promise types:
>
>    1.
>
>    non-resumable / immediately returning (expected<T, E>)
>    1.
>
>       set_result
>       2.
>
>       lacks {initial,final}_suspend? (currently unspecified)
>       2.
>
>    internally-resumable / eventually returning (future<T>)
>    1.
>
>       set_result
>       3.
>
>    externally-resumable (generator<T>)
>    1.
>
>       yield_value
>       4.
>
>    mutually-resumable / eventually returning (async_generator<T>)
>    1.
>
>       yield_value
>       2. set_result
>
>
> The key point is where it is *safe* to call resume(). You've resolved this
> my making it illegal to call `await` from within an externally-resumable
> function (because it is unsafe to call resume() from within such a
> function) and illegal to call `yield` from within an internally-resumable
> function (because the promise lacks yield_from(), but it is also unsafe to
> call resume() from *outside* such a function).
>
> Unfortunately, given the current specification it is either impossible or
> excessively complicated to safely implement await for a non-resumable type
> such as `expected<T, E>` due to the possibility of (unexpectedly)
> suspending execution, e.g.
>
> expected<T, E> foo() {
>   T1 t = await UnwrapExpected();
>   F f = await ReturnsAFuture();  // Ooops! Unexpected suspend & early
> return!
>   return transform(t);
> }
>
> I think the internal-vs-externally resumable dichotomy is sufficient to
> justify two separate types: resumable_handle<P>, which represents the
> entire resumable function; and suspension_handle<P>, which represents a
> single suspension-point within the function.  From here, we can specialize
> the handle based on the promise type to ensure resume is only present on
> the handle(s) which can safely be resumed.  This is slightly complicated by
> the import/export mechanism, but could be resolved by predicating
> conversion and export operations on the presence of resume() on the handle,
> e.g.
>
> struct cancellable_handle {
>
>  // 18.11.2.1 construct/reset
>
>  cancellable_handle() noexcept;
>
>  cancellable_handle(std::nullptr_t) noexcept;
>
>  cancellable_handle& operator=(nullptr_t) noexcept;
>
>  // 18.11.2.3 capacity
>
>  explicit operator bool() const noexcept;
>
>  // {cancellation}
>
>  void destroy() const;
>
> };
>
> template <>
>
> struct resumable_handle<void> : cancellable_handle {
>
>  // 18.11.2.1 construct/reset
>
>  using cancellable_handle::cancellable_handle;
>
>  resumable_handle& operator=(nullptr_t) noexcept;
>
>  // 18.11.2.2 export/import
>
>  static resumable_handle from_address(void* addr) noexcept;
>
>  void* to_address() const noexcept;
>
>   // 18.11.2.4 resumption
>
>  void operator()() const;
>
>  void resume() const;
>
>  // 18.11.2.5 completion check
>
>  bool done() const noexcept;
>
> };
>
> template <>
>
> struct resumable_handle<ExternallyResumable<P>> : resumable_handle<> {
>
>  // 18.11.2.1 construct/reset
>
>  using resumable_handle<>::resumable_handle;
>
>  resumable_handle& operator=(nullptr_t) noexcept;
>
>  // 18.11.2.6 export/import
>
>  static resumable_handle from_promise(Promise*) noexcept;
>
>  Promise& promise() noexcept;
>
>  Promise const& promise() const noexcept;
>
> };
>
> template <>
>
> struct resumable_handle<InternallyResumable<P>> : cancellable_handle {
>
>  ...
>
> };
>
>
> You end up with a similar implementation for suspension_handle<>.
> Additionally, it seems like you could greatly reduce the need for
> from_promise() by having get_return_object(resumable_handle<P>), rather
> than the void argument list.  Ultimately, supporting non-suspendable types
> (optional<T>, expected<T, E>, etc.) may be deemed out of scope, but I still
> feel that using different types for the resumable_handle and
> suspension_handle (or await_handle) would allow such a change to be made
> compatibly at a later date.
>
> Thanks,
> --Shahms
>
>

--

---
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/.

--089e011772673149970515f89ec1
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hey, Gor, I&#39;m not sure if you&#39;ve had a chance to s=
ee my earlier comments yet or not.=C2=A0 My primary concern is with enablin=
g zero-overhead unwrapping APIs.=C2=A0 Even if it&#39;s decided to be not w=
orth the effort to do so with the current proposal, it would be nice to at =
least enable a future proposal to do so in a backwards-compatible fashion.=
=C2=A0 I think splitting the handle types accomplishes that, but may be mis=
sing some reason for keeping them the same (or at least leaving a path open=
 for converting between the two).<div><br></div><div>Thanks,</div><div>--Sh=
ahms<br><div><br><div class=3D"gmail_quote">On Mon, May 4, 2015 at 11:30 AM=
 Shahms King &lt;<a href=3D"mailto:shahms.king@gmail.com">shahms.king@gmail=
..com</a>&gt; wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Than=
ks for publishing the update, it solves a number of the complications with =
the earlier versions and also clarifies some of my misunderstandings.=C2=A0=
 In fact, the specific mention of the potential problems with await and non=
-eventually returning resumable functions led me notice a similar problem w=
ith non-suspendable &quot;immediately returning&quot; promise types (such a=
s a hypothetical one for expected&lt;T, E&gt;).<div><br></div><div>Fundamen=
tally, I think there are 4 different promise types:</div><div><span><ol sty=
le=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list-style=
-type:lower-alpha;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertica=
l-align:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"line=
-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-alig=
n:baseline;white-space:pre-wrap;background-color:transparent">non-resumable=
 / immediately returning (expected&lt;T, E&gt;)</span></p></li><ol style=3D=
"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list-style-type=
:lower-roman;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-ali=
gn:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"line-heig=
ht:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align:bas=
eline;white-space:pre-wrap;background-color:transparent">set_result</span><=
/p></li><li dir=3D"ltr" style=3D"list-style-type:lower-roman;font-size:15px=
;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;background-colo=
r:transparent"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;marg=
in-bottom:0pt"><span style=3D"vertical-align:baseline;white-space:pre-wrap;=
background-color:transparent">lacks {initial,final}_suspend? (currently uns=
pecified)</span></p></li></ol><li dir=3D"ltr" style=3D"list-style-type:lowe=
r-alpha;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:ba=
seline;background-color:transparent"><p dir=3D"ltr" style=3D"line-height:1.=
38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align:baseline=
;white-space:pre-wrap;background-color:transparent">internally-resumable / =
eventually returning (future&lt;T&gt;)</span></p></li><ol style=3D"margin-t=
op:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list-style-type:lower-ro=
man;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseli=
ne;background-color:transparent"><p dir=3D"ltr" style=3D"line-height:1.38;m=
argin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align:baseline;whi=
te-space:pre-wrap;background-color:transparent">set_result</span></p></li><=
/ol><li dir=3D"ltr" style=3D"list-style-type:lower-alpha;font-size:15px;fon=
t-family:Arial;color:rgb(0,0,0);vertical-align:baseline;background-color:tr=
ansparent"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-b=
ottom:0pt"><span style=3D"vertical-align:baseline;white-space:pre-wrap;back=
ground-color:transparent">externally-resumable (generator&lt;T&gt;)</span><=
/p></li><ol style=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" styl=
e=3D"list-style-type:lower-roman;font-size:15px;font-family:Arial;color:rgb=
(0,0,0);vertical-align:baseline;background-color:transparent"><p dir=3D"ltr=
" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=
=3D"vertical-align:baseline;white-space:pre-wrap;background-color:transpare=
nt">yield_value</span></p></li></ol><li dir=3D"ltr" style=3D"list-style-typ=
e:lower-alpha;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-al=
ign:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"line-hei=
ght:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align:ba=
seline;white-space:pre-wrap;background-color:transparent">mutually-resumabl=
e / eventually returning (async_generator&lt;T&gt;)</span></p></li><ol styl=
e=3D"margin-top:0pt;margin-bottom:0pt"><li dir=3D"ltr" style=3D"list-style-=
type:lower-roman;font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical=
-align:baseline;background-color:transparent"><p dir=3D"ltr" style=3D"line-=
height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent">yield_value</s=
pan></p></li><li dir=3D"ltr" style=3D"list-style-type:lower-roman;font-size=
:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;background=
-color:transparent"><span style=3D"vertical-align:baseline;white-space:pre-=
wrap;background-color:transparent">set_result</span></li></ol></ol><div><fo=
nt color=3D"#000000" face=3D"Arial"><span style=3D"font-size:15px;white-spa=
ce:pre-wrap"><br></span></font></div><div>The key point is where it is *saf=
e* to call resume(). You&#39;ve resolved this my making it illegal to call =
`await` from within an externally-resumable function (because it is unsafe =
to call resume() from within such a function) and illegal to call `yield` f=
rom within an internally-resumable function (because the promise lacks yiel=
d_from(), but it is also unsafe to call resume() from *outside* such a func=
tion).</div><div><br></div><div>Unfortunately, given the current specificat=
ion it is either impossible or excessively complicated to safely implement =
await for a non-resumable type such as `expected&lt;T, E&gt;` due to the po=
ssibility of (unexpectedly) suspending execution, e.g.</div><div><br></div>=
<div>expected&lt;T, E&gt; foo() {</div><div>=C2=A0 T1 t =3D await UnwrapExp=
ected();</div><div>=C2=A0 F f =3D await ReturnsAFuture(); =C2=A0// Ooops! U=
nexpected suspend &amp; early return!</div><div>=C2=A0 return transform(t);=
=C2=A0</div><div>}</div><div><br></div><div>I think the internal-vs-externa=
lly resumable dichotomy is sufficient to justify two separate types: resuma=
ble_handle&lt;P&gt;, which represents the entire resumable function; and su=
spension_handle&lt;P&gt;, which represents a single suspension-point within=
 the function.=C2=A0 From here, we can specialize the handle based on the p=
romise type to ensure resume is only present on the handle(s) which can saf=
ely be resumed.=C2=A0 This is slightly complicated by the import/export mec=
hanism, but could be resolved by predicating conversion and export operatio=
ns on the presence of resume() on the handle, e.g.</div><div><br></div><div=
><span><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-botto=
m:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;colo=
r:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent">struct cancellable_handle {</span></p><p dir=3D"ltr" style=3D"=
line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size=
:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:bas=
eline;white-space:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.=
1 construct/reset</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin=
-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;=
Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-w=
rap;background-color:transparent"> =C2=A0cancellable_handle() noexcept;</sp=
an></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-botto=
m:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;colo=
r:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent"> =C2=A0cancellable_handle(std::nullptr_t) noexcept;</span></p>=
<p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt">=
<span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0=
,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transpa=
rent"> =C2=A0cancellable_handle&amp; operator=3D(nullptr_t) noexcept;</span=
></p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bot=
tom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;co=
lor:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-colo=
r:transparent"> =C2=A0// 18.11.2.3 capacity</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0explici=
t operator bool() const noexcept;</span></p><br><p dir=3D"ltr" style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15=
px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseli=
ne;white-space:pre-wrap;background-color:transparent"> =C2=A0// {cancellati=
on}</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margi=
n-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#3=
9;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background=
-color:transparent"> =C2=A0void destroy() const;</span></p><p dir=3D"ltr" s=
tyle=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"f=
ont-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-a=
lign:baseline;white-space:pre-wrap;background-color:transparent">};</span><=
/p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-botto=
m:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;colo=
r:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent">template &lt;&gt;</span></p><p dir=3D"ltr" style=3D"line-heigh=
t:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font=
-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;whit=
e-space:pre-wrap;background-color:transparent">struct resumable_handle&lt;v=
oid&gt; : cancellable_handle {</span></p><p dir=3D"ltr" style=3D"line-heigh=
t:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font=
-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;whit=
e-space:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.1 construc=
t/reset</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier Ne=
w&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;backgr=
ound-color:transparent"> =C2=A0using cancellable_handle::cancellable_handle=
;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-=
bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;=
;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-c=
olor:transparent"> =C2=A0resumable_handle&amp; operator=3D(nullptr_t) noexc=
ept;</span></p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;=
margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier N=
ew&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;backg=
round-color:transparent"> =C2=A0// 18.11.2.2 export/import</span></p><p dir=
=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span =
style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);=
vertical-align:baseline;white-space:pre-wrap;background-color:transparent">=
 =C2=A0static resumable_handle from_address(void* addr) noexcept;</span></p=
><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"=
><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(=
0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transp=
arent"> =C2=A0void* to_address() const noexcept;</span></p><p dir=3D"ltr" s=
tyle=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"f=
ont-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-a=
lign:baseline;white-space:pre-wrap;background-color:transparent"> </span></=
p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt=
"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb=
(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:trans=
parent"> =C2=A0// 18.11.2.4 resumption</span></p><p dir=3D"ltr" style=3D"li=
ne-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:1=
5px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:basel=
ine;white-space:pre-wrap;background-color:transparent"> =C2=A0void operator=
()() const;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0=
pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courie=
r New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;ba=
ckground-color:transparent"> =C2=A0void resume() const;</span></p><br><p di=
r=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span=
 style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0)=
;vertical-align:baseline;white-space:pre-wrap;background-color:transparent"=
> =C2=A0// 18.11.2.5 completion check</span></p><p dir=3D"ltr" style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15=
px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseli=
ne;white-space:pre-wrap;background-color:transparent"> =C2=A0bool done() co=
nst noexcept;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top=
:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Cour=
ier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;=
background-color:transparent">};</span></p><br><p dir=3D"ltr" style=3D"line=
-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15p=
x;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baselin=
e;white-space:pre-wrap;background-color:transparent">template &lt;&gt;</spa=
n></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom=
:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color=
:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:t=
ransparent">struct resumable_handle&lt;ExternallyResumable&lt;P&gt;&gt; : r=
esumable_handle&lt;&gt; {</span></p><p dir=3D"ltr" style=3D"line-height:1.3=
8;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-fami=
ly:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-spa=
ce:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.1 construct/res=
et</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin=
-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39=
;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-=
color:transparent"> =C2=A0using resumable_handle&lt;&gt;::resumable_handle;=
</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-b=
ottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;=
color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-co=
lor:transparent"> =C2=A0resumable_handle&amp; operator=3D(nullptr_t) noexce=
pt;</span></p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier Ne=
w&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;backgr=
ound-color:transparent"> =C2=A0// 18.11.2.6 export/import</span></p><p dir=
=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span =
style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);=
vertical-align:baseline;white-space:pre-wrap;background-color:transparent">=
 =C2=A0static resumable_handle from_promise(Promise*) noexcept;</span></p><=
p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><=
span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,=
0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transpar=
ent"> =C2=A0Promise&amp; promise() noexcept;</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0Promise=
 const&amp; promise() const noexcept;</span></p><p dir=3D"ltr" style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15=
px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseli=
ne;white-space:pre-wrap;background-color:transparent">};</span></p><br><p d=
ir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><spa=
n style=3D"font-size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0=
);vertical-align:baseline;white-space:pre-wrap;background-color:transparent=
">template &lt;&gt;</span></p><p dir=3D"ltr" style=3D"line-height:1.38;marg=
in-top:0pt;margin-bottom:0pt"><span style=3D"font-size:15px;font-family:&#3=
9;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline;white-space:pre=
-wrap;background-color:transparent">struct resumable_handle&lt;InternallyRe=
sumable&lt;P&gt;&gt; : cancellable_handle {</span></p><p dir=3D"ltr" style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"><span style=3D"font-=
size:15px;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align=
:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0...</sp=
an></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-botto=
m:0pt"><span style=3D"font-size:15px;font-family:&#39;Courier New&#39;;colo=
r:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent">};</span></p><div><br></div><div><span style=3D"font-size:15px=
;font-family:&#39;Courier New&#39;;color:rgb(0,0,0);vertical-align:baseline=
;white-space:pre-wrap;background-color:transparent"><br></span></div><div>Y=
ou end up with a similar implementation for suspension_handle&lt;&gt;.=C2=
=A0 Additionally, it seems like you could greatly reduce the need for from_=
promise() by having get_return_object(resumable_handle&lt;P&gt;), rather th=
an the void argument list.=C2=A0 Ultimately, supporting non-suspendable typ=
es (optional&lt;T&gt;, expected&lt;T, E&gt;, etc.) may be deemed out of sco=
pe, but I still feel that using different types for the resumable_handle an=
d suspension_handle (or await_handle) would allow such a change to be made =
compatibly at a later date.</div><div><br></div><div>Thanks,</div><div>--Sh=
ahms</div></span></div><div><br></div></span></div></div></blockquote></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&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 />

--089e011772673149970515f89ec1--

.


Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 17 May 2015 18:49:36 -0700 (PDT)
Raw View
------=_Part_545_1655785623.1431913776432
Content-Type: multipart/alternative;
 boundary="----=_Part_546_1695867935.1431913776432"

------=_Part_546_1695867935.1431913776432
Content-Type: text/plain; charset=UTF-8

Hi Shahms:

Your resumable function classification and identifying the case where we
would like to get a compile time error is spot on.
I think in addition to "no initial_suspend / final_suspend" that will mark
the resumable function as "can never suspend", we need to also have traits
that can explain that awaiting on certain types must never result in
suspension.

Say:

is_suspendable_v<T> == true for arbitrary type T, but, for optional and
expected you will specialize it to be:

is_suspendable_v<optional<T>> == false.

I am not sure how suggested changes to resumable_handle will help, as
resumable_handle is what compiler gives to the library, not, the other way
around.

Gor

P.S.

Here a post from vcblog on related matter:

~~~~~~~~~

Yes, it can work with optional and expected. Though to make the experience
truly awesome, we would need to introduce some mechanism that can express
whether a return object of a resumable function can express expansion of a
particular monadic class.

optional<T> can represent either a value or the absence of value

expected<T> can represent either a value or the absence of value with a
reason why not

future<T> can represent, please wait, a value or the absence of value with
a reason why not

Thus in a resumable function returning a future<T>, it is fine to await on
expression of any type that can be represented by the future, thus, you can
await on optional, expected, future or some other async construct.

If a resumable function returns expected<T> or optional<T>, awaiting on an
expression which type represents value not here yet, should not be possible.

At the moment, I don't have a mechanism in the proposal to deal with that.

I am looking for suggestions and ideas.

I have a half-baked idea that I am not sure I like that looks something
like that:

if resumable promise does not contain initial_suspend and final_suspend
members, that means that resumable function cannot be suspended.

There also should be a trait, let say, "suspendable<T>" that will default
to "true_type", for arbitrary awaitable type, but, for optional and
expected will say false.

When the compiler figures out that resumable promise does not support
suspension (absence of initial_suspend / final_suspend members), it will
not compile your code, if you await on an expression of any type for which
suspendable says true.

On Monday, May 4, 2015 at 11:30:05 AM UTC-7, Shahms King wrote:

> Thanks for publishing the update, it solves a number of the complications
> with the earlier versions and also clarifies some of my misunderstandings.
> In fact, the specific mention of the potential problems with await and
> non-eventually returning resumable functions led me notice a similar
> problem with non-suspendable "immediately returning" promise types (such as
> a hypothetical one for expected<T, E>).
>
> Fundamentally, I think there are 4 different promise types:
>
>    1.
>
>    non-resumable / immediately returning (expected<T, E>)
>    1.
>
>       set_result
>       2.
>
>       lacks {initial,final}_suspend? (currently unspecified)
>       2.
>
>    internally-resumable / eventually returning (future<T>)
>    1.
>
>       set_result
>       3.
>
>    externally-resumable (generator<T>)
>    1.
>
>       yield_value
>       4.
>
>    mutually-resumable / eventually returning (async_generator<T>)
>    1.
>
>       yield_value
>       2. set_result
>
>
> The key point is where it is *safe* to call resume(). You've resolved this
> my making it illegal to call `await` from within an externally-resumable
> function (because it is unsafe to call resume() from within such a
> function) and illegal to call `yield` from within an internally-resumable
> function (because the promise lacks yield_from(), but it is also unsafe to
> call resume() from *outside* such a function).
>
> Unfortunately, given the current specification it is either impossible or
> excessively complicated to safely implement await for a non-resumable type
> such as `expected<T, E>` due to the possibility of (unexpectedly)
> suspending execution, e.g.
>
> expected<T, E> foo() {
>   T1 t = await UnwrapExpected();
>   F f = await ReturnsAFuture();  // Ooops! Unexpected suspend & early
> return!
>   return transform(t);
> }
>
> I think the internal-vs-externally resumable dichotomy is sufficient to
> justify two separate types: resumable_handle<P>, which represents the
> entire resumable function; and suspension_handle<P>, which represents a
> single suspension-point within the function.  From here, we can specialize
> the handle based on the promise type to ensure resume is only present on
> the handle(s) which can safely be resumed.  This is slightly complicated by
> the import/export mechanism, but could be resolved by predicating
> conversion and export operations on the presence of resume() on the handle,
> e.g.
>
> struct cancellable_handle {
>
>  // 18.11.2.1 construct/reset
>
>  cancellable_handle() noexcept;
>
>  cancellable_handle(std::nullptr_t) noexcept;
>
>  cancellable_handle& operator=(nullptr_t) noexcept;
>
>  // 18.11.2.3 capacity
>
>  explicit operator bool() const noexcept;
>
>  // {cancellation}
>
>  void destroy() const;
>
> };
>
> template <>
>
> struct resumable_handle<void> : cancellable_handle {
>
>  // 18.11.2.1 construct/reset
>
>  using cancellable_handle::cancellable_handle;
>
>  resumable_handle& operator=(nullptr_t) noexcept;
>
>  // 18.11.2.2 export/import
>
>  static resumable_handle from_address(void* addr) noexcept;
>
>  void* to_address() const noexcept;
>
>   // 18.11.2.4 resumption
>
>  void operator()() const;
>
>  void resume() const;
>
>  // 18.11.2.5 completion check
>
>  bool done() const noexcept;
>
> };
>
> template <>
>
> struct resumable_handle<ExternallyResumable<P>> : resumable_handle<> {
>
>  // 18.11.2.1 construct/reset
>
>  using resumable_handle<>::resumable_handle;
>
>  resumable_handle& operator=(nullptr_t) noexcept;
>
>  // 18.11.2.6 export/import
>
>  static resumable_handle from_promise(Promise*) noexcept;
>
>  Promise& promise() noexcept;
>
>  Promise const& promise() const noexcept;
>
> };
>
> template <>
>
> struct resumable_handle<InternallyResumable<P>> : cancellable_handle {
>
>  ...
>
> };
>
>
> You end up with a similar implementation for suspension_handle<>.
> Additionally, it seems like you could greatly reduce the need for
> from_promise() by having get_return_object(resumable_handle<P>), rather
> than the void argument list.  Ultimately, supporting non-suspendable types
> (optional<T>, expected<T, E>, etc.) may be deemed out of scope, but I still
> feel that using different types for the resumable_handle and
> suspension_handle (or await_handle) would allow such a change to be made
> compatibly at a later date.
>
> Thanks,
> --Shahms
>
>

--

---
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_546_1695867935.1431913776432
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Hi Shahms:</div><div><br></div><div>Your resumable fu=
nction classification and identifying the case where we would like to get a=
 compile time error is spot on.</div><div>I think in addition to "no initia=
l_suspend / final_suspend" that will mark the resumable function as "can ne=
ver suspend", we need to also have traits that can explain that awaiting on=
 certain types must never result in suspension.</div><div><br></div><div>Sa=
y:</div><div><br></div><div>is_suspendable_v&lt;T&gt; =3D=3D true for arbit=
rary type T, but, for optional and expected you will specialize it to be:</=
div><div><br></div><div>is_suspendable_v&lt;optional&lt;T&gt;&gt; =3D=3D fa=
lse.</div><div><br></div><div>I am not sure how suggested changes to resuma=
ble_handle will help, as resumable_handle is what compiler gives to the lib=
rary, not, the other way around.</div><div><br></div><div>Gor</div><div><br=
></div><div>P.S.</div><div><br></div><div>Here a post from vcblog on relate=
d matter:</div><div><br></div><div><p>~~~~~~~~~</p><p>Yes, it can work with=
 optional and expected. Though to make the experience truly awesome, we wou=
ld need to introduce some mechanism that can express whether a return objec=
t of a resumable function can express expansion of a particular monadic cla=
ss.</p><p>optional&lt;T&gt; can represent either a value or the absence of =
value</p><p>expected&lt;T&gt; can represent either a value or the absence o=
f value with a reason why not</p><p>future&lt;T&gt; can represent, please w=
ait, a value or the absence of value with a reason why not</p><p>Thus in a =
resumable function returning a future&lt;T&gt;, it is fine to await on expr=
ession of any type that can be represented by the future, thus, you can awa=
it on optional, expected, future or some other async construct.</p><p>If a =
resumable function returns expected&lt;T&gt; or optional&lt;T&gt;, awaiting=
 on an expression which type represents value not here yet, should not be p=
ossible.</p><p>At the moment, I don't have a mechanism in the proposal to d=
eal with that.</p><p>I am looking for suggestions and ideas.</p><p>I have a=
 half-baked idea that I am not sure I like that looks something like that:<=
/p><p>if resumable promise does not contain initial_suspend and final_suspe=
nd members, that means that resumable function cannot be suspended.</p><p>T=
here also should be a trait, let say, "suspendable&lt;T&gt;" that will defa=
ult to "true_type", for arbitrary awaitable type, but, for optional and exp=
ected will say false.</p><p>When the compiler figures out that resumable pr=
omise does not support suspension (absence of initial_suspend / final_suspe=
nd members), it will not compile your code, if you await on an expression o=
f any type for which suspendable says true.<br><br>On Monday, May 4, 2015 a=
t 11:30:05 AM UTC-7, Shahms King wrote:</p></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">Thanks for publishing the update, it solves a number of=
 the complications with the earlier versions and also clarifies some of my =
misunderstandings.&nbsp; In fact, the specific mention of the potential pro=
blems with await and non-eventually returning resumable functions led me no=
tice a similar problem with non-suspendable "immediately returning" promise=
 types (such as a hypothetical one for expected&lt;T, E&gt;).<div><br></div=
><div>Fundamentally, I think there are 4 different promise types:</div><div=
><span><ol style=3D"margin-top: 0pt; margin-bottom: 0pt;"><li style=3D"colo=
r: rgb(0, 0, 0); font-family: Arial; font-size: 15px; vertical-align: basel=
ine; list-style-type: lower-alpha; background-color: transparent;" dir=3D"l=
tr"><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" di=
r=3D"ltr"><span style=3D"vertical-align: baseline; white-space: pre-wrap; b=
ackground-color: transparent;">non-resumable / immediately returning (expec=
ted&lt;T, E&gt;)</span></p></li><ol style=3D"margin-top: 0pt; margin-bottom=
: 0pt;"><li style=3D"color: rgb(0, 0, 0); font-family: Arial; font-size: 15=
px; vertical-align: baseline; list-style-type: lower-roman; background-colo=
r: transparent;" dir=3D"ltr"><p style=3D"line-height: 1.38; margin-top: 0pt=
; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D"vertical-align: baseline;=
 white-space: pre-wrap; background-color: transparent;">set_result</span></=
p></li><li style=3D"color: rgb(0, 0, 0); font-family: Arial; font-size: 15p=
x; vertical-align: baseline; list-style-type: lower-roman; background-color=
: transparent;" dir=3D"ltr"><p style=3D"line-height: 1.38; margin-top: 0pt;=
 margin-bottom: 0pt;" dir=3D"ltr"><span style=3D"vertical-align: baseline; =
white-space: pre-wrap; background-color: transparent;">lacks {initial,final=
}_suspend? (currently unspecified)</span></p></li></ol><li style=3D"color: =
rgb(0, 0, 0); font-family: Arial; font-size: 15px; vertical-align: baseline=
; list-style-type: lower-alpha; background-color: transparent;" dir=3D"ltr"=
><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=
=3D"ltr"><span style=3D"vertical-align: baseline; white-space: pre-wrap; ba=
ckground-color: transparent;">internally-resumable / eventually returning (=
future&lt;T&gt;)</span></p></li><ol style=3D"margin-top: 0pt; margin-bottom=
: 0pt;"><li style=3D"color: rgb(0, 0, 0); font-family: Arial; font-size: 15=
px; vertical-align: baseline; list-style-type: lower-roman; background-colo=
r: transparent;" dir=3D"ltr"><p style=3D"line-height: 1.38; margin-top: 0pt=
; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D"vertical-align: baseline;=
 white-space: pre-wrap; background-color: transparent;">set_result</span></=
p></li></ol><li style=3D"color: rgb(0, 0, 0); font-family: Arial; font-size=
: 15px; vertical-align: baseline; list-style-type: lower-alpha; background-=
color: transparent;" dir=3D"ltr"><p style=3D"line-height: 1.38; margin-top:=
 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D"vertical-align: basel=
ine; white-space: pre-wrap; background-color: transparent;">externally-resu=
mable (generator&lt;T&gt;)</span></p></li><ol style=3D"margin-top: 0pt; mar=
gin-bottom: 0pt;"><li style=3D"color: rgb(0, 0, 0); font-family: Arial; fon=
t-size: 15px; vertical-align: baseline; list-style-type: lower-roman; backg=
round-color: transparent;" dir=3D"ltr"><p style=3D"line-height: 1.38; margi=
n-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D"vertical-align:=
 baseline; white-space: pre-wrap; background-color: transparent;">yield_val=
ue</span></p></li></ol><li style=3D"color: rgb(0, 0, 0); font-family: Arial=
; font-size: 15px; vertical-align: baseline; list-style-type: lower-alpha; =
background-color: transparent;" dir=3D"ltr"><p style=3D"line-height: 1.38; =
margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D"vertical-a=
lign: baseline; white-space: pre-wrap; background-color: transparent;">mutu=
ally-resumable / eventually returning (async_generator&lt;T&gt;)</span></p>=
</li><ol style=3D"margin-top: 0pt; margin-bottom: 0pt;"><li style=3D"color:=
 rgb(0, 0, 0); font-family: Arial; font-size: 15px; vertical-align: baselin=
e; list-style-type: lower-roman; background-color: transparent;" dir=3D"ltr=
"><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=
=3D"ltr"><span style=3D"vertical-align: baseline; white-space: pre-wrap; ba=
ckground-color: transparent;">yield_value</span></p></li><li style=3D"color=
: rgb(0, 0, 0); font-family: Arial; font-size: 15px; vertical-align: baseli=
ne; list-style-type: lower-roman; background-color: transparent;" dir=3D"lt=
r"><span style=3D"vertical-align: baseline; white-space: pre-wrap; backgrou=
nd-color: transparent;">set_result</span></li></ol></ol><div><font color=3D=
"#000000" face=3D"Arial"><span style=3D"font-size: 15px; white-space: pre-w=
rap;"><br></span></font></div><div>The key point is where it is *safe* to c=
all resume(). You've resolved this my making it illegal to call `await` fro=
m within an externally-resumable function (because it is unsafe to call res=
ume() from within such a function) and illegal to call `yield` from within =
an internally-resumable function (because the promise lacks yield_from(), b=
ut it is also unsafe to call resume() from *outside* such a function).</div=
><div><br></div><div>Unfortunately, given the current specification it is e=
ither impossible or excessively complicated to safely implement await for a=
 non-resumable type such as `expected&lt;T, E&gt;` due to the possibility o=
f (unexpectedly) suspending execution, e.g.</div><div><br></div><div>expect=
ed&lt;T, E&gt; foo() {</div><div>&nbsp; T1 t =3D await UnwrapExpected();</d=
iv><div>&nbsp; F f =3D await ReturnsAFuture(); &nbsp;// Ooops! Unexpected s=
uspend &amp; early return!</div><div>&nbsp; return transform(t);&nbsp;</div=
><div>}</div><div><br></div><div>I think the internal-vs-externally resumab=
le dichotomy is sufficient to justify two separate types: resumable_handle&=
lt;P&gt;, which represents the entire resumable function; and suspension_ha=
ndle&lt;P&gt;, which represents a single suspension-point within the functi=
on.&nbsp; From here, we can specialize the handle based on the promise type=
 to ensure resume is only present on the handle(s) which can safely be resu=
med.&nbsp; This is slightly complicated by the import/export mechanism, but=
 could be resolved by predicating conversion and export operations on the p=
resence of resume() on the handle, e.g.</div><div><br></div><div><span><p s=
tyle=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr=
"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size=
: 15px; vertical-align: baseline; white-space: pre-wrap; background-color: =
transparent;'>struct cancellable_handle {</span></p><p style=3D"line-height=
: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'co=
lor: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-al=
ign: baseline; white-space: pre-wrap; background-color: transparent;'> &nbs=
p;// 18.11.2.1 construct/reset</span></p><p style=3D"line-height: 1.38; mar=
gin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0,=
 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: baseli=
ne; white-space: pre-wrap; background-color: transparent;'> &nbsp;cancellab=
le_handle() noexcept;</span></p><p style=3D"line-height: 1.38; margin-top: =
0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); f=
ont-family: "Courier New"; font-size: 15px; vertical-align: baseline; white=
-space: pre-wrap; background-color: transparent;'> &nbsp;cancellable_handle=
(std::<wbr>nullptr_t) noexcept;</span></p><p style=3D"line-height: 1.38; ma=
rgin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0=
, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: basel=
ine; white-space: pre-wrap; background-color: transparent;'> &nbsp;cancella=
ble_handle&amp; operator=3D(nullptr_t) noexcept;</span></p><br><p style=3D"=
line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span =
style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; =
vertical-align: baseline; white-space: pre-wrap; background-color: transpar=
ent;'> &nbsp;// 18.11.2.3 capacity</span></p><p style=3D"line-height: 1.38;=
 margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rg=
b(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: ba=
seline; white-space: pre-wrap; background-color: transparent;'> &nbsp;expli=
cit operator bool() const noexcept;</span></p><br><p style=3D"line-height: =
1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'colo=
r: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-alig=
n: baseline; white-space: pre-wrap; background-color: transparent;'> &nbsp;=
// {cancellation}</span></p><p style=3D"line-height: 1.38; margin-top: 0pt;=
 margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-=
family: "Courier New"; font-size: 15px; vertical-align: baseline; white-spa=
ce: pre-wrap; background-color: transparent;'> &nbsp;void destroy() const;<=
/span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0p=
t;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier N=
ew"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap; back=
ground-color: transparent;'>};</span></p><br><p style=3D"line-height: 1.38;=
 margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rg=
b(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: ba=
seline; white-space: pre-wrap; background-color: transparent;'>template &lt=
;&gt;</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bott=
om: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Cou=
rier New"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap=
; background-color: transparent;'>struct resumable_handle&lt;void&gt; : can=
cellable_handle {</span></p><p style=3D"line-height: 1.38; margin-top: 0pt;=
 margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-=
family: "Courier New"; font-size: 15px; vertical-align: baseline; white-spa=
ce: pre-wrap; background-color: transparent;'> &nbsp;// 18.11.2.1 construct=
/reset</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bot=
tom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Co=
urier New"; font-size: 15px; vertical-align: baseline; white-space: pre-wra=
p; background-color: transparent;'> &nbsp;using cancellable_handle::<wbr>ca=
ncellable_handle;</span></p><p style=3D"line-height: 1.38; margin-top: 0pt;=
 margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-=
family: "Courier New"; font-size: 15px; vertical-align: baseline; white-spa=
ce: pre-wrap; background-color: transparent;'> &nbsp;resumable_handle&amp; =
operator=3D(nullptr_t) noexcept;</span></p><br><p style=3D"line-height: 1.3=
8; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: =
rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: =
baseline; white-space: pre-wrap; background-color: transparent;'> &nbsp;// =
18.11.2.2 export/import</span></p><p style=3D"line-height: 1.38; margin-top=
: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0);=
 font-family: "Courier New"; font-size: 15px; vertical-align: baseline; whi=
te-space: pre-wrap; background-color: transparent;'> &nbsp;static resumable=
_handle from_address(void* addr) noexcept;</span></p><p style=3D"line-heigh=
t: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'c=
olor: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-a=
lign: baseline; white-space: pre-wrap; background-color: transparent;'> &nb=
sp;void* to_address() const noexcept;</span></p><p style=3D"line-height: 1.=
38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color:=
 rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align:=
 baseline; white-space: pre-wrap; background-color: transparent;'> </span><=
/p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=
=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; fo=
nt-size: 15px; vertical-align: baseline; white-space: pre-wrap; background-=
color: transparent;'> &nbsp;// 18.11.2.4 resumption</span></p><p style=3D"l=
ine-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span s=
tyle=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; v=
ertical-align: baseline; white-space: pre-wrap; background-color: transpare=
nt;'> &nbsp;void operator()() const;</span></p><p style=3D"line-height: 1.3=
8; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: =
rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: =
baseline; white-space: pre-wrap; background-color: transparent;'> &nbsp;voi=
d resume() const;</span></p><br><p style=3D"line-height: 1.38; margin-top: =
0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); f=
ont-family: "Courier New"; font-size: 15px; vertical-align: baseline; white=
-space: pre-wrap; background-color: transparent;'> &nbsp;// 18.11.2.5 compl=
etion check</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margi=
n-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family=
: "Courier New"; font-size: 15px; vertical-align: baseline; white-space: pr=
e-wrap; background-color: transparent;'> &nbsp;bool done() const noexcept;<=
/span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0p=
t;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier N=
ew"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap; back=
ground-color: transparent;'>};</span></p><br><p style=3D"line-height: 1.38;=
 margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rg=
b(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align: ba=
seline; white-space: pre-wrap; background-color: transparent;'>template &lt=
;&gt;</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bott=
om: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Cou=
rier New"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap=
; background-color: transparent;'>struct resumable_handle&lt;<wbr>Externall=
yResumable&lt;P&gt;&gt; : resumable_handle&lt;&gt; {</span></p><p style=3D"=
line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span =
style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; =
vertical-align: baseline; white-space: pre-wrap; background-color: transpar=
ent;'> &nbsp;// 18.11.2.1 construct/reset</span></p><p style=3D"line-height=
: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'co=
lor: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-al=
ign: baseline; white-space: pre-wrap; background-color: transparent;'> &nbs=
p;using resumable_handle&lt;&gt;::resumable_<wbr>handle;</span></p><p style=
=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><s=
pan style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15=
px; vertical-align: baseline; white-space: pre-wrap; background-color: tran=
sparent;'> &nbsp;resumable_handle&amp; operator=3D(nullptr_t) noexcept;</sp=
an></p><br><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0=
pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier =
New"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap; bac=
kground-color: transparent;'> &nbsp;// 18.11.2.6 export/import</span></p><p=
 style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"l=
tr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-si=
ze: 15px; vertical-align: baseline; white-space: pre-wrap; background-color=
: transparent;'> &nbsp;static resumable_handle from_promise(Promise*) noexc=
ept;</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-botto=
m: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Cour=
ier New"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap;=
 background-color: transparent;'> &nbsp;Promise&amp; promise() noexcept;</s=
pan></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;=
" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courier New=
"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap; backgr=
ound-color: transparent;'> &nbsp;Promise const&amp; promise() const noexcep=
t;</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-bottom:=
 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "Courie=
r New"; font-size: 15px; vertical-align: baseline; white-space: pre-wrap; b=
ackground-color: transparent;'>};</span></p><br><p style=3D"line-height: 1.=
38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color:=
 rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; vertical-align:=
 baseline; white-space: pre-wrap; background-color: transparent;'>template =
&lt;&gt;</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; margin-b=
ottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-family: "=
Courier New"; font-size: 15px; vertical-align: baseline; white-space: pre-w=
rap; background-color: transparent;'>struct resumable_handle&lt;<wbr>Intern=
allyResumable&lt;P&gt;&gt; : cancellable_handle {</span></p><p style=3D"lin=
e-height: 1.38; margin-top: 0pt; margin-bottom: 0pt;" dir=3D"ltr"><span sty=
le=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size: 15px; ver=
tical-align: baseline; white-space: pre-wrap; background-color: transparent=
;'> &nbsp;...</span></p><p style=3D"line-height: 1.38; margin-top: 0pt; mar=
gin-bottom: 0pt;" dir=3D"ltr"><span style=3D'color: rgb(0, 0, 0); font-fami=
ly: "Courier New"; font-size: 15px; vertical-align: baseline; white-space: =
pre-wrap; background-color: transparent;'>};</span></p><div><br></div><div>=
<span style=3D'color: rgb(0, 0, 0); font-family: "Courier New"; font-size: =
15px; vertical-align: baseline; white-space: pre-wrap; background-color: tr=
ansparent;'><br></span></div><div>You end up with a similar implementation =
for suspension_handle&lt;&gt;.&nbsp; Additionally, it seems like you could =
greatly reduce the need for from_promise() by having get_return_object(resu=
mable_<wbr>handle&lt;P&gt;), rather than the void argument list.&nbsp; Ulti=
mately, supporting non-suspendable types (optional&lt;T&gt;, expected&lt;T,=
 E&gt;, etc.) may be deemed out of scope, but I still feel that using diffe=
rent types for the resumable_handle and suspension_handle (or await_handle)=
 would allow such a change to be made compatibly at a later date.</div><div=
><br></div><div>Thanks,</div><div>--Shahms</div></span></div><div><br></div=
></span></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&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_546_1695867935.1431913776432--
------=_Part_545_1655785623.1431913776432--

.


Author: Shahms King <shahms.king@gmail.com>
Date: Fri, 29 May 2015 23:22:23 +0000
Raw View
--001a113db7b63cff55051740c01b
Content-Type: text/plain; charset=UTF-8

Thanks, Gor!

On Sun, May 17, 2015 at 6:49 PM Gor Nishanov <gornishanov@gmail.com> wrote:

> Hi Shahms:
>
> Your resumable function classification and identifying the case where we
> would like to get a compile time error is spot on.
> I think in addition to "no initial_suspend / final_suspend" that will mark
> the resumable function as "can never suspend", we need to also have traits
> that can explain that awaiting on certain types must never result in
> suspension.
>
> Say:
>
> is_suspendable_v<T> == true for arbitrary type T, but, for optional and
> expected you will specialize it to be:
>
> is_suspendable_v<optional<T>> == false.
>

It seems like this could be covered by the lack of a promise_type for T or
the lack of initial/final_suspend on that promise type, but an explicit
type trait wouldn't hurt.


>
> I am not sure how suggested changes to resumable_handle will help, as
> resumable_handle is what compiler gives to the library, not, the other way
> around.
>

Sure, the compiler gives the handle to the library, but the modifications
to the handle type allow the compiler to express valid operations on that
handle using the existing type system.


> Gor
>
> P.S.
>
> Here a post from vcblog on related matter:
>
> ~~~~~~~~~
>
> Yes, it can work with optional and expected. Though to make the experience
> truly awesome, we would need to introduce some mechanism that can express
> whether a return object of a resumable function can express expansion of a
> particular monadic class.
>
> optional<T> can represent either a value or the absence of value
>
> expected<T> can represent either a value or the absence of value with a
> reason why not
>
> future<T> can represent, please wait, a value or the absence of value with
> a reason why not
>
> Thus in a resumable function returning a future<T>, it is fine to await on
> expression of any type that can be represented by the future, thus, you can
> await on optional, expected, future or some other async construct.
>
> If a resumable function returns expected<T> or optional<T>, awaiting on an
> expression which type represents value not here yet, should not be possible.
>
> At the moment, I don't have a mechanism in the proposal to deal with that.
>
> I am looking for suggestions and ideas.
>
This is the problem splitting the handle types aims to solve.
Specifically, calling resume() or to_address() on a non-suspendable promise
becomes a compiler error because the handle lacks those members.  In
addition to resovling the problem presented by:

optional<T> foo() {
  auto a = await some_future();
  ...
}

It also addresses the (similar) yield problem as the internal handle type
will lack those members, while the external handle has them.  I'm
envisioning something like:

struct generator_promise_type {
    generator<T> get_return_object(resumable_handle<generator_promise_type>
handle) {
  // precondition: &handle.promise() == this
  return generator<T>{handle};
}
  ...
};

Such that rather than having to go through hole of
resumable_handle<P>::from_promise(*this), the compiler directly supplies
the resumable_handle to the promise's get_return_object().

From what I can tell, this *should* obviate the need for the from_promise()
function entirely.  Similarly, it does away with the arbitrary restriction
on yield/await, which could go back to the earlier specification as
syntactic sugar around await, e.g.

struct _Yielder {
  ...
  void await_suspend(await_handle<P> handle) {
    handle.promise().yield_value(m_value);
  }
  T m_value;
};

template<typename T>
__yield(T&& value) {
  return _Yielder<T>(std::foward<T>(value));
}

yield foo; // becomes effectively await __yield(foo);

That means that calling await on a non-suspendable awaitable is safe from
with a non-eventually returning function, e.g.

generator<T> foo() {
  yield await expected_value();  // Either yield if present or exit.
}

> I have a half-baked idea that I am not sure I like that looks something
> like that:
>
> if resumable promise does not contain initial_suspend and final_suspend
> members, that means that resumable function cannot be suspended.
>
> There also should be a trait, let say, "suspendable<T>" that will default
> to "true_type", for arbitrary awaitable type, but, for optional and
> expected will say false.
>
> When the compiler figures out that resumable promise does not support
> suspension (absence of initial_suspend / final_suspend members), it will
> not compile your code, if you await on an expression of any type for which
> suspendable says true.
>
 I actually like the explicit type trait, I'm just not sure it's necessary
if we can give the handle different members such that only valid operations
are allowed on it.

Thanks again,
--Shahms

>
> On Monday, May 4, 2015 at 11:30:05 AM UTC-7, Shahms King wrote:
>
>> Thanks for publishing the update, it solves a number of the complications
>> with the earlier versions and also clarifies some of my misunderstandings.
>> In fact, the specific mention of the potential problems with await and
>> non-eventually returning resumable functions led me notice a similar
>> problem with non-suspendable "immediately returning" promise types (such as
>> a hypothetical one for expected<T, E>).
>>
>> Fundamentally, I think there are 4 different promise types:
>>
>>    1.
>>
>>    non-resumable / immediately returning (expected<T, E>)
>>    1.
>>
>>       set_result
>>       2.
>>
>>       lacks {initial,final}_suspend? (currently unspecified)
>>       2.
>>
>>    internally-resumable / eventually returning (future<T>)
>>    1.
>>
>>       set_result
>>       3.
>>
>>    externally-resumable (generator<T>)
>>    1.
>>
>>       yield_value
>>       4.
>>
>>    mutually-resumable / eventually returning (async_generator<T>)
>>    1.
>>
>>       yield_value
>>       2. set_result
>>
>>
>> The key point is where it is *safe* to call resume(). You've resolved
>> this my making it illegal to call `await` from within an
>> externally-resumable function (because it is unsafe to call resume() from
>> within such a function) and illegal to call `yield` from within an
>> internally-resumable function (because the promise lacks yield_from(), but
>> it is also unsafe to call resume() from *outside* such a function).
>>
>> Unfortunately, given the current specification it is either impossible or
>> excessively complicated to safely implement await for a non-resumable type
>> such as `expected<T, E>` due to the possibility of (unexpectedly)
>> suspending execution, e.g.
>>
>> expected<T, E> foo() {
>>   T1 t = await UnwrapExpected();
>>   F f = await ReturnsAFuture();  // Ooops! Unexpected suspend & early
>> return!
>>   return transform(t);
>> }
>>
>> I think the internal-vs-externally resumable dichotomy is sufficient to
>> justify two separate types: resumable_handle<P>, which represents the
>> entire resumable function; and suspension_handle<P>, which represents a
>> single suspension-point within the function.  From here, we can specialize
>> the handle based on the promise type to ensure resume is only present on
>> the handle(s) which can safely be resumed.  This is slightly complicated by
>> the import/export mechanism, but could be resolved by predicating
>> conversion and export operations on the presence of resume() on the handle,
>> e.g.
>>
>> struct cancellable_handle {
>>
>>  // 18.11.2.1 construct/reset
>>
>>  cancellable_handle() noexcept;
>>
>>  cancellable_handle(std::nullptr_t) noexcept;
>>
>>  cancellable_handle& operator=(nullptr_t) noexcept;
>>
>>  // 18.11.2.3 capacity
>>
>>  explicit operator bool() const noexcept;
>>
>>  // {cancellation}
>>
>>  void destroy() const;
>>
>> };
>>
>> template <>
>>
>> struct resumable_handle<void> : cancellable_handle {
>>
>>  // 18.11.2.1 construct/reset
>>
>>  using cancellable_handle::cancellable_handle;
>>
>>  resumable_handle& operator=(nullptr_t) noexcept;
>>
>>  // 18.11.2.2 export/import
>>
>>  static resumable_handle from_address(void* addr) noexcept;
>>
>>  void* to_address() const noexcept;
>>
>>   // 18.11.2.4 resumption
>>
>>  void operator()() const;
>>
>>  void resume() const;
>>
>>  // 18.11.2.5 completion check
>>
>>  bool done() const noexcept;
>>
>> };
>>
>> template <>
>>
>> struct resumable_handle<ExternallyResumable<P>> : resumable_handle<> {
>>
>>  // 18.11.2.1 construct/reset
>>
>>  using resumable_handle<>::resumable_handle;
>>
>>  resumable_handle& operator=(nullptr_t) noexcept;
>>
>>  // 18.11.2.6 export/import
>>
>>  static resumable_handle from_promise(Promise*) noexcept;
>>
>>  Promise& promise() noexcept;
>>
>>  Promise const& promise() const noexcept;
>>
>> };
>>
>> template <>
>>
>> struct resumable_handle<InternallyResumable<P>> : cancellable_handle {
>>
>>  ...
>>
>> };
>>
>>
>> You end up with a similar implementation for suspension_handle<>.
>> Additionally, it seems like you could greatly reduce the need for
>> from_promise() by having get_return_object(resumable_handle<P>), rather
>> than the void argument list.  Ultimately, supporting non-suspendable types
>> (optional<T>, expected<T, E>, etc.) may be deemed out of scope, but I still
>> feel that using different types for the resumable_handle and
>> suspension_handle (or await_handle) would allow such a change to be made
>> compatibly at a later date.
>>
>> Thanks,
>> --Shahms
>>
>>  --
>
> ---
> 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/.
>

--

---
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/.

--001a113db7b63cff55051740c01b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Thanks, Gor!<br><div class=3D"gmail_quote"><div dir=3D"ltr=
"><br></div><div dir=3D"ltr">On Sun, May 17, 2015 at 6:49 PM Gor Nishanov &=
lt;<a href=3D"mailto:gornishanov@gmail.com">gornishanov@gmail.com</a>&gt; w=
rote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex=
;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Hi Shah=
ms:</div><div><br></div><div>Your resumable function classification and ide=
ntifying the case where we would like to get a compile time error is spot o=
n.</div><div>I think in addition to &quot;no initial_suspend / final_suspen=
d&quot; that will mark the resumable function as &quot;can never suspend&qu=
ot;, we need to also have traits that can explain that awaiting on certain =
types must never result in suspension.</div><div><br></div><div>Say:</div><=
div><br></div><div>is_suspendable_v&lt;T&gt; =3D=3D true for arbitrary type=
 T, but, for optional and expected you will specialize it to be:</div><div>=
<br></div><div>is_suspendable_v&lt;optional&lt;T&gt;&gt; =3D=3D false.</div=
></div></blockquote><div><br></div><div>It seems like this could be covered=
 by the lack of a promise_type for T or the lack of initial/final_suspend o=
n that promise type, but an explicit type trait wouldn&#39;t hurt.</div><di=
v>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><br></di=
v><div>I am not sure how suggested changes to resumable_handle will help, a=
s resumable_handle is what compiler gives to the library, not, the other wa=
y around.</div></div></blockquote><div><br></div><div>Sure, the compiler gi=
ves the handle to the library, but the modifications to the handle type all=
ow the compiler to express valid operations on that handle using the existi=
ng type system.</div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div><br></div><div>Gor</div><div><br></div><div>P.S.</div><div><b=
r></div><div>Here a post from vcblog on related matter:</div><div><br></div=
></div><div dir=3D"ltr"><div><p>~~~~~~~~~</p><p>Yes, it can work with optio=
nal and expected. Though to make the experience truly awesome, we would nee=
d to introduce some mechanism that can express whether a return object of a=
 resumable function can express expansion of a particular monadic class.</p=
><p>optional&lt;T&gt; can represent either a value or the absence of value<=
/p><p>expected&lt;T&gt; can represent either a value or the absence of valu=
e with a reason why not</p><p>future&lt;T&gt; can represent, please wait, a=
 value or the absence of value with a reason why not</p><p>Thus in a resuma=
ble function returning a future&lt;T&gt;, it is fine to await on expression=
 of any type that can be represented by the future, thus, you can await on =
optional, expected, future or some other async construct.</p><p>If a resuma=
ble function returns expected&lt;T&gt; or optional&lt;T&gt;, awaiting on an=
 expression which type represents value not here yet, should not be possibl=
e.</p><p>At the moment, I don&#39;t have a mechanism in the proposal to dea=
l with that.</p><p>I am looking for suggestions and ideas.</p></div></div><=
/blockquote><div>This is the problem splitting the handle types aims to sol=
ve.=C2=A0 Specifically, calling resume() or to_address() on a non-suspendab=
le promise becomes a compiler error because the handle lacks those members.=
=C2=A0 In addition to resovling the problem presented by:</div><div><br></d=
iv><div>optional&lt;T&gt; foo() {</div><div>=C2=A0 auto a =3D await some_fu=
ture();</div><div>=C2=A0 ...=C2=A0</div><div>}</div><div>=C2=A0</div><div>I=
t also addresses the (similar) yield problem as the internal handle type wi=
ll lack those members, while the external handle has them.=C2=A0 I&#39;m en=
visioning something like:</div><div><br></div><div>struct generator_promise=
_type {</div><div>=C2=A0 =C2=A0 generator&lt;T&gt; get_return_object(resuma=
ble_handle&lt;generator_promise_type&gt; handle) {</div><div>=C2=A0 // prec=
ondition: &amp;handle.promise() =3D=3D this</div><div>=C2=A0 return generat=
or&lt;T&gt;{handle};</div><div>}</div><div>=C2=A0 ...</div><div>};</div><di=
v><br></div><div>Such that rather than having to go through hole of resumab=
le_handle&lt;P&gt;::from_promise(*this), the compiler directly supplies the=
 resumable_handle to the promise&#39;s get_return_object().</div><div><br><=
/div><div>From what I can tell, this *should* obviate the need for the from=
_promise() function entirely.=C2=A0 Similarly, it does away with the arbitr=
ary restriction on yield/await, which could go back to the earlier specific=
ation as syntactic sugar around await, e.g.</div><div><br></div><div>struct=
 _Yielder {</div><div>=C2=A0 ...</div><div>=C2=A0 void await_suspend(await_=
handle&lt;P&gt; handle) {</div><div>=C2=A0 =C2=A0 handle.promise().yield_va=
lue(m_value);</div><div>=C2=A0 }</div><div>=C2=A0 T m_value;</div><div>};</=
div><div><br></div><div>template&lt;typename T&gt;</div><div>__yield(T&amp;=
&amp; value) {</div><div>=C2=A0 return _Yielder&lt;T&gt;(std::foward&lt;T&g=
t;(value));</div><div>}</div><div><br></div><div>yield foo; // becomes effe=
ctively await __yield(foo);</div><div><br></div><div>That means that callin=
g await on a non-suspendable awaitable is safe from with a non-eventually r=
eturning function, e.g.</div><div><br></div><div>generator&lt;T&gt; foo() {=
</div><div>=C2=A0 yield await expected_value(); =C2=A0// Either yield if pr=
esent or exit.</div><div>}</div><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr"><div><p>I have a half-baked idea that I am not sure I like that looks =
something like that:</p><p>if resumable promise does not contain initial_su=
spend and final_suspend members, that means that resumable function cannot =
be suspended.</p><p>There also should be a trait, let say, &quot;suspendabl=
e&lt;T&gt;&quot; that will default to &quot;true_type&quot;, for arbitrary =
awaitable type, but, for optional and expected will say false.</p></div></d=
iv><div dir=3D"ltr"><div><p>When the compiler figures out that resumable pr=
omise does not support suspension (absence of initial_suspend / final_suspe=
nd members), it will not compile your code, if you await on an expression o=
f any type for which suspendable says true.<br></p></div></div></blockquote=
><div>=C2=A0I actually like the explicit type trait, I&#39;m just not sure =
it&#39;s necessary if we can give the handle different members such that on=
ly valid operations are allowed on it.<br></div><div><br></div><div>Thanks =
again,</div><div>--Shahms</div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div><p><br></p></div></div><div dir=3D"ltr"><div><p>On Monday, May 4, =
2015 at 11:30:05 AM UTC-7, Shahms King wrote:</p></div></div><div dir=3D"lt=
r"><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">Thanks for publishing the update, it s=
olves a number of the complications with the earlier versions and also clar=
ifies some of my misunderstandings.=C2=A0 In fact, the specific mention of =
the potential problems with await and non-eventually returning resumable fu=
nctions led me notice a similar problem with non-suspendable &quot;immediat=
ely returning&quot; promise types (such as a hypothetical one for expected&=
lt;T, E&gt;).<div><br></div><div>Fundamentally, I think there are 4 differe=
nt promise types:</div><div><span><ol style=3D"margin-top:0pt;margin-bottom=
:0pt"><li style=3D"color:rgb(0,0,0);font-family:Arial;font-size:15px;vertic=
al-align:baseline;list-style-type:lower-alpha;background-color:transparent"=
 dir=3D"ltr"><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt"=
 dir=3D"ltr"><span style=3D"vertical-align:baseline;white-space:pre-wrap;ba=
ckground-color:transparent">non-resumable / immediately returning (expected=
&lt;T, E&gt;)</span></p></li><ol style=3D"margin-top:0pt;margin-bottom:0pt"=
><li style=3D"color:rgb(0,0,0);font-family:Arial;font-size:15px;vertical-al=
ign:baseline;list-style-type:lower-roman;background-color:transparent" dir=
=3D"ltr"><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=
=3D"ltr"><span style=3D"vertical-align:baseline;white-space:pre-wrap;backgr=
ound-color:transparent">set_result</span></p></li><li style=3D"color:rgb(0,=
0,0);font-family:Arial;font-size:15px;vertical-align:baseline;list-style-ty=
pe:lower-roman;background-color:transparent" dir=3D"ltr"><p style=3D"line-h=
eight:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"ver=
tical-align:baseline;white-space:pre-wrap;background-color:transparent">lac=
ks {initial,final}_suspend? (currently unspecified)</span></p></li></ol><li=
 style=3D"color:rgb(0,0,0);font-family:Arial;font-size:15px;vertical-align:=
baseline;list-style-type:lower-alpha;background-color:transparent" dir=3D"l=
tr"><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"l=
tr"><span style=3D"vertical-align:baseline;white-space:pre-wrap;background-=
color:transparent">internally-resumable / eventually returning (future&lt;T=
&gt;)</span></p></li><ol style=3D"margin-top:0pt;margin-bottom:0pt"><li sty=
le=3D"color:rgb(0,0,0);font-family:Arial;font-size:15px;vertical-align:base=
line;list-style-type:lower-roman;background-color:transparent" dir=3D"ltr">=
<p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr">=
<span style=3D"vertical-align:baseline;white-space:pre-wrap;background-colo=
r:transparent">set_result</span></p></li></ol><li style=3D"color:rgb(0,0,0)=
;font-family:Arial;font-size:15px;vertical-align:baseline;list-style-type:l=
ower-alpha;background-color:transparent" dir=3D"ltr"><p style=3D"line-heigh=
t:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"vertica=
l-align:baseline;white-space:pre-wrap;background-color:transparent">externa=
lly-resumable (generator&lt;T&gt;)</span></p></li><ol style=3D"margin-top:0=
pt;margin-bottom:0pt"><li style=3D"color:rgb(0,0,0);font-family:Arial;font-=
size:15px;vertical-align:baseline;list-style-type:lower-roman;background-co=
lor:transparent" dir=3D"ltr"><p style=3D"line-height:1.38;margin-top:0pt;ma=
rgin-bottom:0pt" dir=3D"ltr"><span style=3D"vertical-align:baseline;white-s=
pace:pre-wrap;background-color:transparent">yield_value</span></p></li></ol=
><li style=3D"color:rgb(0,0,0);font-family:Arial;font-size:15px;vertical-al=
ign:baseline;list-style-type:lower-alpha;background-color:transparent" dir=
=3D"ltr"><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=
=3D"ltr"><span style=3D"vertical-align:baseline;white-space:pre-wrap;backgr=
ound-color:transparent">mutually-resumable / eventually returning (async_ge=
nerator&lt;T&gt;)</span></p></li><ol style=3D"margin-top:0pt;margin-bottom:=
0pt"><li style=3D"color:rgb(0,0,0);font-family:Arial;font-size:15px;vertica=
l-align:baseline;list-style-type:lower-roman;background-color:transparent" =
dir=3D"ltr"><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" =
dir=3D"ltr"><span style=3D"vertical-align:baseline;white-space:pre-wrap;bac=
kground-color:transparent">yield_value</span></p></li><li style=3D"color:rg=
b(0,0,0);font-family:Arial;font-size:15px;vertical-align:baseline;list-styl=
e-type:lower-roman;background-color:transparent" dir=3D"ltr"><span style=3D=
"vertical-align:baseline;white-space:pre-wrap;background-color:transparent"=
>set_result</span></li></ol></ol><div><font color=3D"#000000" face=3D"Arial=
"><span style=3D"font-size:15px;white-space:pre-wrap"><br></span></font></d=
iv><div>The key point is where it is *safe* to call resume(). You&#39;ve re=
solved this my making it illegal to call `await` from within an externally-=
resumable function (because it is unsafe to call resume() from within such =
a function) and illegal to call `yield` from within an internally-resumable=
 function (because the promise lacks yield_from(), but it is also unsafe to=
 call resume() from *outside* such a function).</div><div><br></div><div>Un=
fortunately, given the current specification it is either impossible or exc=
essively complicated to safely implement await for a non-resumable type suc=
h as `expected&lt;T, E&gt;` due to the possibility of (unexpectedly) suspen=
ding execution, e.g.</div><div><br></div><div>expected&lt;T, E&gt; foo() {<=
/div><div>=C2=A0 T1 t =3D await UnwrapExpected();</div><div>=C2=A0 F f =3D =
await ReturnsAFuture(); =C2=A0// Ooops! Unexpected suspend &amp; early retu=
rn!</div><div>=C2=A0 return transform(t);=C2=A0</div><div>}</div><div><br><=
/div><div>I think the internal-vs-externally resumable dichotomy is suffici=
ent to justify two separate types: resumable_handle&lt;P&gt;, which represe=
nts the entire resumable function; and suspension_handle&lt;P&gt;, which re=
presents a single suspension-point within the function.=C2=A0 From here, we=
 can specialize the handle based on the promise type to ensure resume is on=
ly present on the handle(s) which can safely be resumed.=C2=A0 This is slig=
htly complicated by the import/export mechanism, but could be resolved by p=
redicating conversion and export operations on the presence of resume() on =
the handle, e.g.</div><div><br></div><div><span><p style=3D"line-height:1.3=
8;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,=
0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertical-align:base=
line;white-space:pre-wrap;background-color:transparent">struct cancellable_=
handle {</span></p><p style=3D"line-height:1.38;margin-top:0pt;margin-botto=
m:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courie=
r New&quot;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;bac=
kground-color:transparent"> =C2=A0// 18.11.2.1 construct/reset</span></p><p=
 style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><s=
pan style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size=
:15px;vertical-align:baseline;white-space:pre-wrap;background-color:transpa=
rent"> =C2=A0cancellable_handle() noexcept;</span></p><p style=3D"line-heig=
ht:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:=
rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertical-alig=
n:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0cancel=
lable_handle(std::nullptr_t) noexcept;</span></p><p style=3D"line-height:1.=
38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0=
,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertical-align:bas=
eline;white-space:pre-wrap;background-color:transparent"> =C2=A0cancellable=
_handle&amp; operator=3D(nullptr_t) noexcept;</span></p><br><p style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"=
color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertica=
l-align:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0=
// 18.11.2.3 capacity</span></p><p style=3D"line-height:1.38;margin-top:0pt=
;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family=
:&quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-space=
:pre-wrap;background-color:transparent"> =C2=A0explicit operator bool() con=
st noexcept;</span></p><br><p style=3D"line-height:1.38;margin-top:0pt;marg=
in-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quo=
t;Courier New&quot;;font-size:15px;vertical-align:baseline;white-space:pre-=
wrap;background-color:transparent"> =C2=A0// {cancellation}</span></p><p st=
yle=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span=
 style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15=
px;vertical-align:baseline;white-space:pre-wrap;background-color:transparen=
t"> =C2=A0void destroy() const;</span></p><p style=3D"line-height:1.38;marg=
in-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);f=
ont-family:&quot;Courier New&quot;;font-size:15px;vertical-align:baseline;w=
hite-space:pre-wrap;background-color:transparent">};</span></p><br><p style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span st=
yle=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;=
vertical-align:baseline;white-space:pre-wrap;background-color:transparent">=
template &lt;&gt;</span></p><p style=3D"line-height:1.38;margin-top:0pt;mar=
gin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&qu=
ot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-space:pre=
-wrap;background-color:transparent">struct resumable_handle&lt;void&gt; : c=
ancellable_handle {</span></p><p style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&=
quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-space:p=
re-wrap;background-color:transparent"> =C2=A0// 18.11.2.1 construct/reset</=
span></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=
=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot=
;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-co=
lor:transparent"> =C2=A0using cancellable_handle::cancellable_handle;</span=
></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"=
ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;fo=
nt-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent"> =C2=A0resumable_handle&amp; operator=3D(nullptr_t) noexcept;<=
/span></p><br><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt=
" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New=
&quot;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;backgrou=
nd-color:transparent"> =C2=A0// 18.11.2.2 export/import</span></p><p style=
=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span st=
yle=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;=
vertical-align:baseline;white-space:pre-wrap;background-color:transparent">=
 =C2=A0static resumable_handle from_address(void* addr) noexcept;</span></p=
><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"=
><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-s=
ize:15px;vertical-align:baseline;white-space:pre-wrap;background-color:tran=
sparent"> =C2=A0void* to_address() const noexcept;</span></p><p style=3D"li=
ne-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D=
"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertic=
al-align:baseline;white-space:pre-wrap;background-color:transparent"> </spa=
n></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D=
"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;f=
ont-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color=
:transparent"> =C2=A0// 18.11.2.4 resumption</span></p><p style=3D"line-hei=
ght:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color=
:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertical-ali=
gn:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0void =
operator()() const;</span></p><p style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&=
quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-space:p=
re-wrap;background-color:transparent"> =C2=A0void resume() const;</span></p=
><br><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"=
ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;fo=
nt-size:15px;vertical-align:baseline;white-space:pre-wrap;background-color:=
transparent"> =C2=A0// 18.11.2.5 completion check</span></p><p style=3D"lin=
e-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"=
color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertica=
l-align:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0=
bool done() const noexcept;</span></p><p style=3D"line-height:1.38;margin-t=
op:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-=
family:&quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white=
-space:pre-wrap;background-color:transparent">};</span></p><br><p style=3D"=
line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=
=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;ver=
tical-align:baseline;white-space:pre-wrap;background-color:transparent">tem=
plate &lt;&gt;</span></p><p style=3D"line-height:1.38;margin-top:0pt;margin=
-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;=
Courier New&quot;;font-size:15px;vertical-align:baseline;white-space:pre-wr=
ap;background-color:transparent">struct resumable_handle&lt;ExternallyResum=
able&lt;P&gt;&gt; : resumable_handle&lt;&gt; {</span></p><p style=3D"line-h=
eight:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"col=
or:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertical-a=
lign:baseline;white-space:pre-wrap;background-color:transparent"> =C2=A0// =
18.11.2.1 construct/reset</span></p><p style=3D"line-height:1.38;margin-top=
:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-fa=
mily:&quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-s=
pace:pre-wrap;background-color:transparent"> =C2=A0using resumable_handle&l=
t;&gt;::resumable_handle;</span></p><p style=3D"line-height:1.38;margin-top=
:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-fa=
mily:&quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-s=
pace:pre-wrap;background-color:transparent"> =C2=A0resumable_handle&amp; op=
erator=3D(nullptr_t) noexcept;</span></p><br><p style=3D"line-height:1.38;m=
argin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0=
);font-family:&quot;Courier New&quot;;font-size:15px;vertical-align:baselin=
e;white-space:pre-wrap;background-color:transparent"> =C2=A0// 18.11.2.6 ex=
port/import</span></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bo=
ttom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Cou=
rier New&quot;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;=
background-color:transparent"> =C2=A0static resumable_handle from_promise(P=
romise*) noexcept;</span></p><p style=3D"line-height:1.38;margin-top:0pt;ma=
rgin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&q=
uot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-space:pr=
e-wrap;background-color:transparent"> =C2=A0Promise&amp; promise() noexcept=
;</span></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" =
dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&q=
uot;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;background=
-color:transparent"> =C2=A0Promise const&amp; promise() const noexcept;</sp=
an></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=
=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot=
;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;background-co=
lor:transparent">};</span></p><br><p style=3D"line-height:1.38;margin-top:0=
pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-fami=
ly:&quot;Courier New&quot;;font-size:15px;vertical-align:baseline;white-spa=
ce:pre-wrap;background-color:transparent">template &lt;&gt;</span></p><p st=
yle=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span=
 style=3D"color:rgb(0,0,0);font-family:&quot;Courier New&quot;;font-size:15=
px;vertical-align:baseline;white-space:pre-wrap;background-color:transparen=
t">struct resumable_handle&lt;InternallyResumable&lt;P&gt;&gt; : cancellabl=
e_handle {</span></p><p style=3D"line-height:1.38;margin-top:0pt;margin-bot=
tom:0pt" dir=3D"ltr"><span style=3D"color:rgb(0,0,0);font-family:&quot;Cour=
ier New&quot;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;b=
ackground-color:transparent"> =C2=A0...</span></p><p style=3D"line-height:1=
..38;margin-top:0pt;margin-bottom:0pt" dir=3D"ltr"><span style=3D"color:rgb(=
0,0,0);font-family:&quot;Courier New&quot;;font-size:15px;vertical-align:ba=
seline;white-space:pre-wrap;background-color:transparent">};</span></p><div=
><br></div><div><span style=3D"color:rgb(0,0,0);font-family:&quot;Courier N=
ew&quot;;font-size:15px;vertical-align:baseline;white-space:pre-wrap;backgr=
ound-color:transparent"><br></span></div><div>You end up with a similar imp=
lementation for suspension_handle&lt;&gt;.=C2=A0 Additionally, it seems lik=
e you could greatly reduce the need for from_promise() by having get_return=
_object(resumable_handle&lt;P&gt;), rather than the void argument list.=C2=
=A0 Ultimately, supporting non-suspendable types (optional&lt;T&gt;, expect=
ed&lt;T, E&gt;, etc.) may be deemed out of scope, but I still feel that usi=
ng different types for the resumable_handle and suspension_handle (or await=
_handle) would allow such a change to be made compatibly at a later date.</=
div><div><br></div><div>Thanks,</div><div>--Shahms</div></span></div><div><=
br></div></span></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&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" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
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>
</blockquote></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 />

--001a113db7b63cff55051740c01b--

.