Topic: Constructive comments on P0054R0: Coroutines
Author: TONGARI J <tongari95@gmail.com>
Date: Wed, 7 Oct 2015 07:34:28 -0700 (PDT)
Raw View
------=_Part_7607_1893098870.1444228468367
Content-Type: multipart/alternative;
boundary="----=_Part_7608_1887856342.1444228468369"
------=_Part_7608_1887856342.1444228468369
Content-Type: text/plain; charset=UTF-8
Hi Gor,
I have some comments on the current design:
RAII
coroutine_handle is just like raw-pointer, it doesn't manages the resource
and it's even more dangerous and error-prone than manual memory management.
coroutine_handle should embrace RAII semantic, more precisely, the
unique-semantic. There should be at most one instance executing the same
coroutine at the same time.
When coroutine_handle is destructed, it should force the stack to be
unwound.
I'd suggest renaming coroutine_handle to coroutine. std::coroutine<> should
define a promise_type, so it can be used as the *Coroutine Return Type*:
std::coroutine<> coro(int i, int e)
{
for (; i != e; ++i)
{
await std::suspend_always{};
std::cout << i;
}
}
....// usageauto c = coro(1, 10);while (c)
{
c();
std::cout << ", ";
}
There's no need for a done() member function, when the coroutine is done,
it'll reset itself so operator bool will report false.
std::coroutine<Promise> has a static void destroy(Promise*) function, which
destroys the coroutine-frame from the Promise pointer. Unlike the original
proposal, in which destroy is a non-static member function and will unwind
the stack, the new destroy is a static function and won't unwind the stack.
The Promise::get_return_object is also changed to accepts a param, i.e. get_return_object(coroutine<Promise>&
coro). The user can now decide when and how to run the coroutine on the
first time.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#case-study>Case Study
Consider the code below:
std::future<void> f()
{
Resource res(...);
await std::suspend_always{};
}
....// usagef().get();
Without RAII, you'll get memory & other resource leaks; with RAII, you'll
get broken_promise exception without any resource leak.
As an additional benefit, a coroutine can now safely cancel itself (i.e.
just suspend it), it also makes cascading cancellation possible without
exceptions.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#implementation>
Implementation
The idea is already implemented in CO2 <https://github.com/jamboree/co2>,
an emulation library based on earlier proposal.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#additional-optional-customization-points-for-promise>Additional
(optional) customization points for Promise
-
void cancel() This allows you specify the behavior of the coroutine when
it is cancelled (i.e. when cancellation_requested() returns true or
coroutine is reset).
-
bool resume() This is called before the coroutine is resumed, if it
returns false, the coroutine won't be resumed, instead, the coroutine
will be detached.
-
void suspend() This is called before the coroutine is gonna be
suspended, however, it won't be called for final_suspend.
Although theoretical there should be at most one instance executing the
same coroutine at the same time, but sometimes you need to resume more than
one concurrently, for example, to support "active-cancellation". The
resume() & suspend() customization points provide such possibility.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#bikeshedding>
Bikeshedding
- on_cancel
- on_resume
- on_suspend
<https://gist.github.com/jamboree/611b8c6551f853956f7d#implementation-1>
Implementation
Also implemented in CO2.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#restoration-of-cancellation_requested>Restoration
of cancellation_requested
I think cancellation_requested is still needed to implement
passive-cancellation.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#inspect-promisevalue_typereturn_type-check-on-return>Inspect
Promise::value_type(return_type), check on return
The return_type information could help the compiler to provide more robust
return behavior. It allows the compiler to check type compatibility before
calling Promise::return_value/void.
- return reference to local warning
// return type is a reference
std::future<int&> f()
{
int a = 9;
await std::experimental::suspend_never{};
return a; // warning wanted
}
- return local variable with the same type as return_type:
// return type and object have the same type
std::future<MoveOnly> f()
{
MoveOnly var;
await std::experimental::suspend_never{};
return var; // `var` should be treated as rvalue-ref
}
The Promise::return_value will get the param as rvalue-ref instead of
lvalue-ref.
- help in case that the Promise::return_value is generic that can't
deduce the type from braced-init:
std::future<Aggregate> f()
{
await std::experimental::suspend_never{};
return {1, 2, 3};
}
<https://gist.github.com/jamboree/611b8c6551f853956f7d#bikeshedding-1>
Bikeshedding
value_type/return_type/result_type
<https://gist.github.com/jamboree/611b8c6551f853956f7d#when-does-stack-unwinding-happen>When
does stack-unwinding happen?
It'd better happen before Promise::return_value/void. Consider a normal
function call:
int f()
{
LovalVar local;
doSomething();
return 0;
}
....// on useint i = f();// `local` should be destructed before we get the return value
We'd expect the stack-frame of f get unwound before it returns, the same
expectation applies to resumable functions as well:
Task<int> f()
{
LovalVar local;
await doSomething();
return 0;
}
....// on useint i = await f();
The implementation of Task may invoke its continuation on return_value/void
or final_suspend, depends on the author's choice. To get the consistent
behavior, stack-unwinding should happen before return_value/void.
I checked the current MSVC implementation, it's done before final_suspend,
and sometimes before return_value/void, which is inconsistent.
See the example <https://gist.github.com/jamboree/9bbe2435677295475f36>.
The result I got is:
[ret_value]
return_value()
~A()
final_suspend()
------
[ret_void]
return_void()
~A()
final_suspend()
------
[ret_void_implicit]
~A()
return_void()
final_suspend()
------
where A is a local variable of the resumable function.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#customization-points>Customization
points
These customization points should be made public (user-accessible):
- await_ready
- await_suspend
- await_resume
What I mean "public" is that the user can call the free functions, like
below:
using std::await_ready;if (await_ready(someAwaitable))
{
...
}
Better yet, the customization points could follow what Eric Niebler has
suggested: https://ericniebler.github.io/std/wg21/D4381.html
Also, operator await needs to be public as well, but I'd suggest renaming
it to get_awaiter, which is easier to write for the user, and also allows
the possibility of Eric's proposal.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#case-study-1>Case
Study
Suppose you want to make a wrapper for any *Awaiatable* that allows you to
wait without extracting the result, it could be implemented this way:
template<class Task>struct ready_awaiter
{
Task task;
bool await_ready()
{
return std::await_ready(task);
}
template<class F>
auto await_suspend(F&& f)
{
return std::await_suspend(task, std::forward<F>(f));
}
void await_resume() noexcept {}
};
template<class Task>inline ready_awaiter<Task> ready_impl(Task&& task)
{
return {std::forward<Task>(task)};
}
template<class Task>inline auto ready(Task&& task)
{
return ready_impl(std::get_awaiter(std::forward<Task>(task)));
}
....// usage
await ready(someAwaitable);
<https://gist.github.com/jamboree/611b8c6551f853956f7d#initialfinal_suspend---bool-or-awaiatable>
initial/final_suspend - bool or Awaiatable?
I don't see why initial/final_suspend needs to return *Awaiatable*.
If initial/final_suspend returns bool, it's just like returning an
*Awaiatable* that onlys defines bool await_suspend.
In the example of final_suspend you shown, it's exactly the same as the bool version.
What am I missing?
On the other hand, yield_value does need to return *Awaiatable*, I also
reported it here
<https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/zEMU_F-QcBo>
..
<https://gist.github.com/jamboree/611b8c6551f853956f7d#syntax-to-specify-an-allocator>Syntax
to specify an allocator
A new clause can be used, for example:
template<class Allocator>
std::future<void> f(Allocator alloc) new(alloc)
{
await ...
}
The is irrelevant to how coroutine_traits *default* allocates, if the user
specifies new(alloc), the alloc will override the default allocation
strategy defined by coroutine_traits.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-vs-resumableasync>auto
await v.s. resumable(async)
P0054R0 draws the idea "Automatically Awaited Awaitables", however, I think
we'd better not to interfere with the type system. The original sample:
auto MyProxy::operator=(int output)
{
struct Awaitable auto await { ... };
return Awaitable{...};
}
could be written this way:
await auto MyProxy::operator=(int output)
{
struct Awaitable { ... };
return Awaitable{...};
}
Note that the await prefix is not part of the type system here, it just
instructs the compiler to await on what it returns.
That said, the "auto await" idea is not flexible enough, consider the
special functions, e.g. constructors & destructors, which could also be
resumable in theory, there's no way for them to use "auto await".
A better solution is to consider something like the approach taken by
Resumable Expressions (P0114R0).
I had a draft describing the joint idea:
https://gist.github.com/jamboree/a2b3fe32eeb8c21e820c
The same example written in the draft will look like:
async auto MyProxy::operator=(int output)
{
struct Awaitable { ... };
return await Awaitable{...};
}
The most interesting part of the draft is "Context-based overloading",
which I haven't seen in other proposals, I'd like to get some feedback from
you.
Thanks.
--
---
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_7608_1887856342.1444228468369
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><span style=3D"color: rgb(51, 51, 51); font-family: 'H=
elvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-se=
rif; font-size: 16px; line-height: 25.6px;">Hi Gor,</span><div><font color=
=3D"#333333" face=3D"Helvetica Neue, Helvetica, Segoe UI, Arial, freesans, =
sans-serif"><span style=3D"font-size: 16px; line-height: 25.6px;"><br></spa=
n></font></div><div><font color=3D"#333333" face=3D"Helvetica Neue, Helveti=
ca, Segoe UI, Arial, freesans, sans-serif"><span style=3D"font-size: 16px; =
line-height: 25.6px;">I have some comments on the current design:<br></span=
></font><div><br></div><div><div><h2 style=3D"box-sizing: border-box; line-=
height: 1.225; font-size: 1.75em; font-weight: bold; padding-bottom: 0.3em;=
border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color:=
rgb(238, 238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Ne=
ue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;">RAII<=
/h2><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family=
: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans,=
sans-serif; font-size: 16px; line-height: 25.6px;"><code style=3D"box-sizi=
ng: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Co=
urier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.=
2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">corou=
tine_handle</code>=C2=A0is just like raw-pointer, it doesn't manages th=
e resource and it's even more dangerous and error-prone than manual mem=
ory management.</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 5=
1); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', A=
rial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><br></p>=
<p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: &#=
39;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, san=
s-serif; font-size: 16px; line-height: 25.6px;"><code style=3D"box-sizing: =
border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courie=
r, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em;=
border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">coroutine=
_handle</code>=C2=A0should embrace RAII semantic, more precisely, the uniqu=
e-semantic. There should be at most one instance executing the same corouti=
ne at the same time.</p><p style=3D"box-sizing: border-box; color: rgb(51, =
51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI=
9;, Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><br=
></p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-famil=
y: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans=
, sans-serif; font-size: 16px; line-height: 25.6px;">When=C2=A0<code style=
=3D"box-sizing: border-box; font-family: Consolas, 'Liberation Mono'=
;, Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; paddin=
g-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392=
157);">coroutine_handle</code>=C2=A0is destructed, it should force the stac=
k to be unwound.</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, =
51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', =
Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><br></p=
><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: &=
#39;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sa=
ns-serif; font-size: 16px; line-height: 25.6px;">I'd suggest renaming=
=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, 'Li=
beration Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-t=
op: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color: rgb=
a(0, 0, 0, 0.0392157);">coroutine_handle</code>=C2=A0to=C2=A0<code style=3D=
"box-sizing: border-box; font-family: Consolas, 'Liberation Mono', =
Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-b=
ottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157=
);">coroutine</code>.=C2=A0<code style=3D"box-sizing: border-box; font-fami=
ly: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-si=
ze: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; =
background-color: rgba(0, 0, 0, 0.0392157);">std::coroutine<></code>=
=C2=A0should define a=C2=A0<code style=3D"box-sizing: border-box; font-fami=
ly: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-si=
ze: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; =
background-color: rgba(0, 0, 0, 0.0392157);">promise_type</code>, so it can=
be used as the=C2=A0<em style=3D"box-sizing: border-box;">Coroutine Return=
Type</em>:</p><div class=3D"highlight highlight-source-c++" style=3D"box-s=
izing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue=
', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-siz=
e: 16px; line-height: 25.6px;"><pre style=3D"box-sizing: border-box; overfl=
ow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier,=
monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; pad=
ding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; back=
ground-color: rgb(247, 247, 247);">std::coroutine<> <span class=3D"pl=
-en" style=3D"box-sizing: border-box; color: rgb(121, 93, 163);">coro</span=
>(<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29,=
93);">int</span> i, <span class=3D"pl-k" style=3D"box-sizing: border-box; =
color: rgb(167, 29, 93);">int</span> e)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">for</span> (; i !=3D e; ++i)
{
await std::suspend_always{};
std::cout << i;
}
}
....
<span class=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, =
150);">// usage</span>
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">auto</span> c =3D coro(<span class=3D"pl-c1" style=3D"box-sizing: bord=
er-box; color: rgb(0, 134, 179);">1</span>, <span class=3D"pl-c1" style=3D"=
box-sizing: border-box; color: rgb(0, 134, 179);">10</span>);
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">while</span> (c)
{
<span class=3D"pl-c1" style=3D"box-sizing: border-box; color: rgb(0, 13=
4, 179);">c</span>();
std::cout << <span class=3D"pl-s" style=3D"box-sizing: border-box=
; color: rgb(24, 54, 145);"><span class=3D"pl-pds" style=3D"box-sizing: bor=
der-box;">"</span>, <span class=3D"pl-pds" style=3D"box-sizing: border=
-box;">"</span></span>;
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">There's no=
need for a=C2=A0<code style=3D"box-sizing: border-box; font-family: Consol=
as, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px=
; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background=
-color: rgba(0, 0, 0, 0.0392157);">done()</code>=C2=A0member function, when=
the coroutine is done, it'll reset itself so=C2=A0<code style=3D"box-s=
izing: border-box; font-family: Consolas, 'Liberation Mono', Menlo,=
Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom:=
0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">op=
erator bool</code>=C2=A0will report=C2=A0<code style=3D"box-sizing: border-=
box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, mono=
space; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border=
-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">false</code>.</p=
><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: &=
#39;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sa=
ns-serif; font-size: 16px; line-height: 25.6px;"><br></p><p style=3D"box-si=
zing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue&=
#39;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size=
: 16px; line-height: 25.6px;"><code style=3D"box-sizing: border-box; font-f=
amily: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font=
-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3p=
x; background-color: rgba(0, 0, 0, 0.0392157);">std::coroutine<Promise&g=
t;</code>=C2=A0has a static=C2=A0<code style=3D"box-sizing: border-box; fon=
t-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; f=
ont-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius:=
3px; background-color: rgba(0, 0, 0, 0.0392157);">void destroy(Promise*)</=
code>=C2=A0function, which destroys the coroutine-frame from the=C2=A0<code=
style=3D"box-sizing: border-box; font-family: Consolas, 'Liberation Mo=
no', Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; =
padding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, =
0.0392157);">Promise</code>=C2=A0pointer. Unlike the original proposal, in =
which=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, &#=
39;Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padd=
ing-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color=
: rgba(0, 0, 0, 0.0392157);">destroy</code>=C2=A0is a non-static member fun=
ction and will unwind the stack, the new=C2=A0<code style=3D"box-sizing: bo=
rder-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier,=
monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; b=
order-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">destroy</co=
de>=C2=A0is a static function and won't unwind the stack.</p><p style=
=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helve=
tica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;=
font-size: 16px; line-height: 25.6px;"><br></p><p style=3D"box-sizing: bor=
der-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Hel=
vetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; l=
ine-height: 25.6px;">The=C2=A0<code style=3D"box-sizing: border-box; font-f=
amily: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font=
-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3p=
x; background-color: rgba(0, 0, 0, 0.0392157);">Promise::get_return_object<=
/code>=C2=A0is also changed to accepts a param, i.e.=C2=A0<code style=3D"bo=
x-sizing: border-box; font-family: Consolas, 'Liberation Mono', Men=
lo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bott=
om: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);"=
>get_return_object(coroutine<Promise>& coro)</code>. The user can=
now decide when and how to run the=C2=A0<code style=3D"box-sizing: border-=
box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, mono=
space; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border=
-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">coroutine</code>=
=C2=A0on the first time.</p><p style=3D"box-sizing: border-box; color: rgb(=
51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe U=
I', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"=
><br></p><h3 style=3D"box-sizing: border-box; line-height: 1.43; font-size:=
1.5em; font-weight: bold; color: rgb(51, 51, 51); font-family: 'Helvet=
ica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"=
><a id=3D"user-content-case-study" class=3D"anchor" href=3D"https://gist.gi=
thub.com/jamboree/611b8c6551f853956f7d#case-study" aria-hidden=3D"true" sty=
le=3D"box-sizing: border-box; color: rgb(64, 120, 192); position: absolute;=
top: 0px; left: 0px; display: block; padding-right: 6px; padding-left: 30p=
x; margin-left: -30px; line-height: 1.2; background-color: transparent;"></=
a>Case Study</h3><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51)=
; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Ari=
al, freesans, sans-serif; font-size: 16px; line-height: 25.6px;">Consider t=
he code below:</p><div class=3D"highlight highlight-source-c++" style=3D"bo=
x-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica N=
eue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-=
size: 16px; line-height: 25.6px;"><pre style=3D"box-sizing: border-box; ove=
rflow: auto; font-family: Consolas, 'Liberation Mono', Menlo, Couri=
er, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; =
padding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; b=
ackground-color: rgb(247, 247, 247);">std::future<<span class=3D"pl-k" s=
tyle=3D"box-sizing: border-box; color: rgb(167, 29, 93);">void</span>> <=
span class=3D"pl-en" style=3D"box-sizing: border-box; color: rgb(121, 93, 1=
63);">f</span>()
{
Resource <span class=3D"pl-smi" style=3D"box-sizing: border-box;">res</=
span>(...);
await std::suspend_always{};
}
....
<span class=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, =
150);">// usage</span>
<span class=3D"pl-en" style=3D"box-sizing: border-box; color: rgb(121, 93, =
163);">f</span>().get();</pre></div><p style=3D"box-sizing: border-box; col=
or: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, '=
;Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: =
25.6px;">Without RAII, you'll get memory & other resource leaks; wi=
th RAII, you'll get=C2=A0<code style=3D"box-sizing: border-box; font-fa=
mily: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-=
size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px=
; background-color: rgba(0, 0, 0, 0.0392157);">broken_promise</code>=C2=A0e=
xception without any resource leak.</p><p style=3D"box-sizing: border-box; =
color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, &=
#39;Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-heigh=
t: 25.6px;"><br></p><p style=3D"box-sizing: border-box; color: rgb(51, 51, =
51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', =
Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;">As an a=
dditional benefit, a coroutine can now safely cancel itself (i.e. just susp=
end it), it also makes cascading cancellation possible without exceptions.<=
/p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family:=
'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, =
sans-serif; font-size: 16px; line-height: 25.6px;"><br></p><h3 style=3D"box=
-sizing: border-box; line-height: 1.43; font-size: 1.5em; font-weight: bold=
; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica,=
'Segoe UI', Arial, freesans, sans-serif;"><a id=3D"user-content-im=
plementation" class=3D"anchor" href=3D"https://gist.github.com/jamboree/611=
b8c6551f853956f7d#implementation" aria-hidden=3D"true" style=3D"box-sizing:=
border-box; color: rgb(64, 120, 192); position: absolute; top: 0px; left: =
0px; display: block; padding-right: 6px; padding-left: 30px; margin-left: -=
30px; line-height: 1.2; background-color: transparent;"></a>Implementation<=
/h3><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family=
: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans,=
sans-serif; font-size: 16px; line-height: 25.6px;">The idea is already imp=
lemented in=C2=A0<a href=3D"https://github.com/jamboree/co2" style=3D"box-s=
izing: border-box; color: rgb(64, 120, 192); background-color: transparent;=
">CO2</a>, an emulation library based on earlier proposal.</p><p style=3D"b=
ox-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica =
Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font=
-size: 16px; line-height: 25.6px;"><br></p><h2 style=3D"box-sizing: border-=
box; line-height: 1.225; font-size: 1.75em; font-weight: bold; padding-bott=
om: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bot=
tom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); font-family: 'He=
lvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-ser=
if;"><a id=3D"user-content-additional-optional-customization-points-for-pro=
mise" class=3D"anchor" href=3D"https://gist.github.com/jamboree/611b8c6551f=
853956f7d#additional-optional-customization-points-for-promise" aria-hidden=
=3D"true" style=3D"box-sizing: border-box; color: rgb(64, 120, 192); positi=
on: absolute; top: 0px; left: 0px; display: block; padding-right: 6px; padd=
ing-left: 30px; margin-left: -30px; line-height: 1; background-color: trans=
parent;"></a>Additional (optional) customization points for Promise</h2><ul=
style=3D"box-sizing: border-box; padding: 0px 0px 0px 2em; color: rgb(51, =
51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI=
9;, Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><li=
style=3D"box-sizing: border-box;"><p style=3D"box-sizing: border-box; marg=
in-top: 16px; margin-bottom: 16px;"><code style=3D"box-sizing: border-box; =
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace=
; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radi=
us: 3px; background-color: rgba(0, 0, 0, 0.0392157);">void cancel()</code>=
=C2=A0This allows you specify the behavior of the coroutine when it is canc=
elled (i.e. when=C2=A0<code style=3D"box-sizing: border-box; font-family: C=
onsolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 1=
3.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; backg=
round-color: rgba(0, 0, 0, 0.0392157);">cancellation_requested()</code>=C2=
=A0returns=C2=A0<code style=3D"box-sizing: border-box; font-family: Consola=
s, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px;=
padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-=
color: rgba(0, 0, 0, 0.0392157);">true</code>=C2=A0or coroutine is reset).<=
/p></li><li style=3D"box-sizing: border-box;"><p style=3D"box-sizing: borde=
r-box; margin-top: 16px; margin-bottom: 16px;"><code style=3D"box-sizing: b=
order-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier=
, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; =
border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">bool resum=
e()</code>=C2=A0This is called before the coroutine is resumed, if it retur=
ns=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, '=
Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding=
-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color: r=
gba(0, 0, 0, 0.0392157);">false</code>, the coroutine won't be resumed,=
instead, the coroutine will be detached.</p></li><li style=3D"box-sizing: =
border-box;"><p style=3D"box-sizing: border-box; margin-top: 16px; margin-b=
ottom: 16px;"><code style=3D"box-sizing: border-box; font-family: Consolas,=
'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; p=
adding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-co=
lor: rgba(0, 0, 0, 0.0392157);">void suspend()</code>=C2=A0This is called b=
efore the coroutine is gonna be suspended, however, it won't be called =
for=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, '=
;Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; paddin=
g-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color: =
rgba(0, 0, 0, 0.0392157);">final_suspend</code>.</p></li></ul><p style=3D"b=
ox-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica =
Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font=
-size: 16px; line-height: 25.6px;">Although theoretical there should be at =
most one instance executing the same coroutine at the same time, but someti=
mes you need to resume more than one concurrently, for example, to support =
"active-cancellation". The=C2=A0<code style=3D"box-sizing: border=
-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, mon=
ospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; borde=
r-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">resume()</code>=
=C2=A0&=C2=A0<code style=3D"box-sizing: border-box; font-family: Consol=
as, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px=
; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background=
-color: rgba(0, 0, 0, 0.0392157);">suspend()</code>=C2=A0customization poin=
ts provide such possibility.</p><p style=3D"box-sizing: border-box; color: =
rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Seg=
oe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6=
px;"><br></p><h3 style=3D"box-sizing: border-box; line-height: 1.43; font-s=
ize: 1.5em; font-weight: bold; color: rgb(51, 51, 51); font-family: 'He=
lvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-ser=
if;"><a id=3D"user-content-bikeshedding" class=3D"anchor" href=3D"https://g=
ist.github.com/jamboree/611b8c6551f853956f7d#bikeshedding" aria-hidden=3D"t=
rue" style=3D"box-sizing: border-box; color: rgb(64, 120, 192); position: a=
bsolute; top: 0px; left: 0px; display: block; padding-right: 6px; padding-l=
eft: 30px; margin-left: -30px; line-height: 1.2; background-color: transpar=
ent;"></a>Bikeshedding</h3><ul style=3D"box-sizing: border-box; padding: 0p=
x 0px 0px 2em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue'=
;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 1=
6px; line-height: 25.6px;"><li style=3D"box-sizing: border-box;">on_cancel<=
/li><li style=3D"box-sizing: border-box;">on_resume</li><li style=3D"box-si=
zing: border-box;">on_suspend</li></ul><h3 style=3D"box-sizing: border-box;=
line-height: 1.43; font-size: 1.5em; font-weight: bold; color: rgb(51, 51,=
51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI',=
Arial, freesans, sans-serif;"><a id=3D"user-content-implementation-1" clas=
s=3D"anchor" href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#=
implementation-1" aria-hidden=3D"true" style=3D"box-sizing: border-box; col=
or: rgb(64, 120, 192); position: absolute; top: 0px; left: 0px; display: bl=
ock; padding-right: 6px; padding-left: 30px; margin-left: -30px; line-heigh=
t: 1.2; background-color: transparent;"></a>Implementation</h3><p style=3D"=
box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica=
Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; fon=
t-size: 16px; line-height: 25.6px;">Also implemented in CO2.</p><p style=3D=
"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetic=
a Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; fo=
nt-size: 16px; line-height: 25.6px;"><br></p><h2 style=3D"box-sizing: borde=
r-box; line-height: 1.225; font-size: 1.75em; font-weight: bold; padding-bo=
ttom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-b=
ottom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); font-family: '=
Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-s=
erif;"><a id=3D"user-content-restoration-of-cancellation_requested" class=
=3D"anchor" href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#r=
estoration-of-cancellation_requested" aria-hidden=3D"true" style=3D"box-siz=
ing: border-box; color: rgb(64, 120, 192); position: absolute; top: 0px; le=
ft: 0px; display: block; padding-right: 6px; padding-left: 30px; margin-lef=
t: -30px; line-height: 1; background-color: transparent;"></a>Restoration o=
f cancellation_requested</h2><p style=3D"box-sizing: border-box; color: rgb=
(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe =
UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;=
">I think=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas=
, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; =
padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-c=
olor: rgba(0, 0, 0, 0.0392157);">cancellation_requested</code>=C2=A0is stil=
l needed to implement passive-cancellation.</p><p style=3D"box-sizing: bord=
er-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helv=
etica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; li=
ne-height: 25.6px;"><br></p><h2 style=3D"box-sizing: border-box; line-heigh=
t: 1.225; font-size: 1.75em; font-weight: bold; padding-bottom: 0.3em; bord=
er-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(=
238, 238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue=
9;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a id=3D"u=
ser-content-inspect-promisevalue_typereturn_type-check-on-return" class=3D"=
anchor" href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#inspe=
ct-promisevalue_typereturn_type-check-on-return" aria-hidden=3D"true" style=
=3D"box-sizing: border-box; color: rgb(64, 120, 192); position: absolute; t=
op: 0px; left: 0px; display: block; padding-right: 6px; padding-left: 30px;=
margin-left: -30px; line-height: 1; background-color: transparent;"></a>In=
spect Promise::value_type(return_type), check on return</h2><p style=3D"box=
-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Ne=
ue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-s=
ize: 16px; line-height: 25.6px;">The=C2=A0<code style=3D"box-sizing: border=
-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, mon=
ospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; borde=
r-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">return_type</co=
de>=C2=A0information could help the compiler to provide more robust=C2=A0<c=
ode style=3D"box-sizing: border-box; font-family: Consolas, 'Liberation=
Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2e=
m; padding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, =
0, 0.0392157);">return</code>=C2=A0behavior. It allows the compiler to chec=
k type compatibility before calling=C2=A0<code style=3D"box-sizing: border-=
box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, mono=
space; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border=
-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">Promise::return_=
value/void</code>.</p><ul style=3D"box-sizing: border-box; padding: 0px 0px=
0px 2em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', He=
lvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; =
line-height: 25.6px;"><li style=3D"box-sizing: border-box;">return referenc=
e to local warning</li></ul><div class=3D"highlight highlight-source-c++" s=
tyle=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'H=
elvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-se=
rif; font-size: 16px; line-height: 25.6px;"><pre style=3D"box-sizing: borde=
r-box; overflow: auto; font-family: Consolas, 'Liberation Mono', Me=
nlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-heig=
ht: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-break:=
normal; background-color: rgb(247, 247, 247);"><span class=3D"pl-c" style=
=3D"box-sizing: border-box; color: rgb(150, 152, 150);">// return type is a=
reference</span>
std::future<<span class=3D"pl-k" style=3D"box-sizing: border-box; color:=
rgb(167, 29, 93);">int</span>&> <span class=3D"pl-en" style=3D"box-=
sizing: border-box; color: rgb(121, 93, 163);">f</span>()
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">int</span> a =3D <span class=3D"pl-c1" style=3D"box-sizing: border=
-box; color: rgb(0, 134, 179);">9</span>;
await std::experimental::suspend_never{};
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> a; <span class=3D"pl-c" style=3D"box-sizing: border-=
box; color: rgb(150, 152, 150);">// warning wanted</span>
}</pre></div><ul style=3D"box-sizing: border-box; padding: 0px 0px 0px 2em;=
color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, =
'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-heig=
ht: 25.6px;"><li style=3D"box-sizing: border-box;">return local variable wi=
th the same type as return_type:</li></ul><div class=3D"highlight highlight=
-source-c++" style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-=
family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, fre=
esans, sans-serif; font-size: 16px; line-height: 25.6px;"><pre style=3D"box=
-sizing: border-box; overflow: auto; font-family: Consolas, 'Liberation=
Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch: nor=
mal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: norma=
l; word-break: normal; background-color: rgb(247, 247, 247);"><span class=
=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, 150);">// r=
eturn type and object have the same type</span>
std::future<MoveOnly> <span class=3D"pl-en" style=3D"box-sizing: bord=
er-box; color: rgb(121, 93, 163);">f</span>()
{
MoveOnly var;
await std::experimental::suspend_never{};
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> var; <span class=3D"pl-c" style=3D"box-sizing: borde=
r-box; color: rgb(150, 152, 150);">// `var` should be treated as rvalue-ref=
</span>
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">The=C2=A0<code=
style=3D"box-sizing: border-box; font-family: Consolas, 'Liberation Mo=
no', Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; =
padding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, =
0.0392157);">Promise::return_value</code>=C2=A0will get the param as rvalue=
-ref instead of lvalue-ref.</p><ul style=3D"box-sizing: border-box; padding=
: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: 'Helvetica Neue=
', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-siz=
e: 16px; line-height: 25.6px;"><li style=3D"box-sizing: border-box;">help i=
n case that the=C2=A0<code style=3D"box-sizing: border-box; font-family: Co=
nsolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13=
..6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; backgr=
ound-color: rgba(0, 0, 0, 0.0392157);">Promise::return_value</code>=C2=A0is=
generic that can't deduce the type from braced-init:</li></ul><div cla=
ss=3D"highlight highlight-source-c++" style=3D"box-sizing: border-box; colo=
r: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, '=
Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 2=
5.6px;"><pre style=3D"box-sizing: border-box; overflow: auto; font-family: =
Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: =
13.6px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radi=
us: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, =
247, 247);">std::future<Aggregate> <span class=3D"pl-en" style=3D"box=
-sizing: border-box; color: rgb(121, 93, 163);">f</span>()
{
await std::experimental::suspend_never{};
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> {<span class=3D"pl-c1" style=3D"box-sizing: border-b=
ox; color: rgb(0, 134, 179);">1</span>, <span class=3D"pl-c1" style=3D"box-=
sizing: border-box; color: rgb(0, 134, 179);">2</span>, <span class=3D"pl-c=
1" style=3D"box-sizing: border-box; color: rgb(0, 134, 179);">3</span>};
}</pre></div><h3 style=3D"box-sizing: border-box; line-height: 1.43; font-s=
ize: 1.5em; font-weight: bold; color: rgb(51, 51, 51); font-family: 'He=
lvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-ser=
if;"><br></h3><h3 style=3D"box-sizing: border-box; line-height: 1.43; font-=
size: 1.5em; font-weight: bold; color: rgb(51, 51, 51); font-family: 'H=
elvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-se=
rif;"><a id=3D"user-content-bikeshedding-1" class=3D"anchor" href=3D"https:=
//gist.github.com/jamboree/611b8c6551f853956f7d#bikeshedding-1" aria-hidden=
=3D"true" style=3D"box-sizing: border-box; color: rgb(64, 120, 192); positi=
on: absolute; top: 0px; left: 0px; display: block; padding-right: 6px; padd=
ing-left: 30px; margin-left: -30px; line-height: 1.2; background-color: tra=
nsparent;"></a>Bikeshedding</h3><p style=3D"box-sizing: border-box; color: =
rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Seg=
oe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6=
px;">value_type/return_type/result_type</p><p style=3D"box-sizing: border-b=
ox; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetic=
a, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-h=
eight: 25.6px;"><br></p><h2 style=3D"box-sizing: border-box; line-height: 1=
..225; font-size: 1.75em; font-weight: bold; padding-bottom: 0.3em; border-b=
ottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238,=
238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue', =
Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a id=3D"user-=
content-when-does-stack-unwinding-happen" class=3D"anchor" href=3D"https://=
gist.github.com/jamboree/611b8c6551f853956f7d#when-does-stack-unwinding-hap=
pen" aria-hidden=3D"true" style=3D"box-sizing: border-box; color: rgb(64, 1=
20, 192); position: absolute; top: 0px; left: 0px; display: block; padding-=
right: 6px; padding-left: 30px; margin-left: -30px; line-height: 1; backgro=
und-color: transparent;"></a>When does stack-unwinding happen?</h2><p style=
=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helve=
tica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;=
font-size: 16px; line-height: 25.6px;">It'd better happen before Promi=
se::return_value/void. Consider a normal function call:</p><div class=3D"hi=
ghlight highlight-source-c++" style=3D"box-sizing: border-box; color: rgb(5=
1, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI=
', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;">=
<pre style=3D"box-sizing: border-box; overflow: auto; font-family: Consolas=
, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; =
font-stretch: normal; line-height: 1.45; padding: 16px; border-radius: 3px;=
word-wrap: normal; word-break: normal; background-color: rgb(247, 247, 247=
);"><span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">int</span> <span class=3D"pl-en" style=3D"box-sizing: border-box; =
color: rgb(121, 93, 163);">f</span>()
{
LovalVar local;
<span class=3D"pl-c1" style=3D"box-sizing: border-box; color: rgb(0, 13=
4, 179);">doSomething</span>();
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> <span class=3D"pl-c1" style=3D"box-sizing: border-bo=
x; color: rgb(0, 134, 179);">0</span>;
}
....
<span class=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, =
150);">// on use</span>
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">int</span> i =3D f();
<span class=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, =
150);">// `local` should be destructed before we get the return value</span=
></pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">We'd expec=
t the stack-frame of=C2=A0<code style=3D"box-sizing: border-box; font-famil=
y: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-siz=
e: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; b=
ackground-color: rgba(0, 0, 0, 0.0392157);">f</code>=C2=A0get unwound befor=
e it returns, the same expectation applies to resumable functions as well:<=
/p><div class=3D"highlight highlight-source-c++" style=3D"box-sizing: borde=
r-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helve=
tica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; lin=
e-height: 25.6px;"><pre style=3D"box-sizing: border-box; overflow: auto; fo=
nt-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; =
font-size: 13.6px; font-stretch: normal; line-height: 1.45; padding: 16px; =
border-radius: 3px; word-wrap: normal; word-break: normal; background-color=
: rgb(247, 247, 247);">Task<<span class=3D"pl-k" style=3D"box-sizing: bo=
rder-box; color: rgb(167, 29, 93);">int</span>> <span class=3D"pl-en" st=
yle=3D"box-sizing: border-box; color: rgb(121, 93, 163);">f</span>()
{
LovalVar local;
await <span class=3D"pl-smi" style=3D"box-sizing: border-box;">doSometh=
ing</span>();
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> <span class=3D"pl-c1" style=3D"box-sizing: border-bo=
x; color: rgb(0, 134, 179);">0</span>;
}
....
<span class=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, =
150);">// on use</span>
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">int</span> i =3D await <span class=3D"pl-en" style=3D"box-sizing: bord=
er-box; color: rgb(121, 93, 163);">f</span>();</pre></div><p style=3D"box-s=
izing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue=
', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-siz=
e: 16px; line-height: 25.6px;">The implementation of=C2=A0<code style=3D"bo=
x-sizing: border-box; font-family: Consolas, 'Liberation Mono', Men=
lo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bott=
om: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);"=
>Task</code>=C2=A0may invoke its continuation on=C2=A0<code style=3D"box-si=
zing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, =
Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: =
0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">ret=
urn_value/void</code>=C2=A0or=C2=A0<code style=3D"box-sizing: border-box; f=
ont-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;=
font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radiu=
s: 3px; background-color: rgba(0, 0, 0, 0.0392157);">final_suspend</code>, =
depends on the author's choice. To get the consistent behavior, stack-u=
nwinding should happen before=C2=A0<code style=3D"box-sizing: border-box; f=
ont-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;=
font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radiu=
s: 3px; background-color: rgba(0, 0, 0, 0.0392157);">return_value/void</cod=
e>.</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-fam=
ily: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesa=
ns, sans-serif; font-size: 16px; line-height: 25.6px;"><br></p><p style=3D"=
box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica=
Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; fon=
t-size: 16px; line-height: 25.6px;">I checked the current MSVC implementati=
on, it's done before=C2=A0<code style=3D"box-sizing: border-box; font-f=
amily: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font=
-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3p=
x; background-color: rgba(0, 0, 0, 0.0392157);">final_suspend</code>, and s=
ometimes before=C2=A0<code style=3D"box-sizing: border-box; font-family: Co=
nsolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13=
..6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; backgr=
ound-color: rgba(0, 0, 0, 0.0392157);">return_value/void</code>, which is i=
nconsistent.</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51);=
font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Aria=
l, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><a href=3D"=
https://gist.github.com/jamboree/9bbe2435677295475f36" style=3D"box-sizing:=
border-box; color: rgb(64, 120, 192); background-color: transparent;">See =
the example</a>.</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, =
51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', =
Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;">The res=
ult I got is:</p><pre style=3D"box-sizing: border-box; overflow: auto; font=
-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; fo=
nt-size: 13.6px; font-stretch: normal; line-height: 1.45; padding: 16px; bo=
rder-radius: 3px; word-wrap: normal; color: rgb(51, 51, 51); background-col=
or: rgb(247, 247, 247);"><code style=3D"box-sizing: border-box; font-family=
: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size=
: 13.6px; border-radius: 3px; word-break: normal; display: inline; max-widt=
h: initial; overflow: initial; line-height: inherit; word-wrap: normal; bac=
kground: transparent;">[ret_value]
return_value()
~A()
final_suspend()
------
[ret_void]
return_void()
~A()
final_suspend()
------
[ret_void_implicit]
~A()
return_void()
final_suspend()
------
</code></pre><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">where=C2=A0<co=
de style=3D"box-sizing: border-box; font-family: Consolas, 'Liberation =
Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em=
; padding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0=
, 0.0392157);">A</code>=C2=A0is a local variable of the resumable function.=
</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family=
: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans,=
sans-serif; font-size: 16px; line-height: 25.6px;"><br></p><h2 style=3D"bo=
x-sizing: border-box; line-height: 1.225; font-size: 1.75em; font-weight: b=
old; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: =
solid; border-bottom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); fon=
t-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, f=
reesans, sans-serif;"><a id=3D"user-content-customization-points" class=3D"=
anchor" href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#custo=
mization-points" aria-hidden=3D"true" style=3D"box-sizing: border-box; colo=
r: rgb(64, 120, 192); position: absolute; top: 0px; left: 0px; display: blo=
ck; padding-right: 6px; padding-left: 30px; margin-left: -30px; line-height=
: 1; background-color: transparent;"></a>Customization points</h2><p style=
=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helve=
tica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;=
font-size: 16px; line-height: 25.6px;">These customization points should b=
e made public (user-accessible):</p><ul style=3D"box-sizing: border-box; pa=
dding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: 'Helvetica=
Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; fon=
t-size: 16px; line-height: 25.6px;"><li style=3D"box-sizing: border-box;">a=
wait_ready</li><li style=3D"box-sizing: border-box;">await_suspend</li><li =
style=3D"box-sizing: border-box;">await_resume</li></ul><p style=3D"box-siz=
ing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue&#=
39;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size:=
16px; line-height: 25.6px;">What I mean "public" is that the use=
r can call the free functions, like below:</p><div class=3D"highlight highl=
ight-source-c++" style=3D"box-sizing: border-box; color: rgb(51, 51, 51); f=
ont-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,=
freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><pre style=3D=
"box-sizing: border-box; overflow: auto; font-family: Consolas, 'Libera=
tion Mono', Menlo, Courier, monospace; font-size: 13.6px; font-stretch:=
normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-wrap: n=
ormal; word-break: normal; background-color: rgb(247, 247, 247);"><span cla=
ss=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">usin=
g</span> std::await_ready;
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">if</span> (await_ready(someAwaitable))
{
...
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">Better yet, th=
e customization points could follow what Eric Niebler has suggested:=C2=A0<=
a href=3D"https://ericniebler.github.io/std/wg21/D4381.html" style=3D"box-s=
izing: border-box; color: rgb(64, 120, 192); background-color: transparent;=
">https://ericniebler.github.io/std/wg21/D4381.html</a></p><p style=3D"box-=
sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neu=
e', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-si=
ze: 16px; line-height: 25.6px;"><br></p><p style=3D"box-sizing: border-box;=
color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, =
'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-heig=
ht: 25.6px;">Also,=C2=A0<code style=3D"box-sizing: border-box; font-family:=
Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size:=
13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; bac=
kground-color: rgba(0, 0, 0, 0.0392157);">operator await</code>=C2=A0needs =
to be public as well, but I'd suggest renaming it to=C2=A0<code style=
=3D"box-sizing: border-box; font-family: Consolas, 'Liberation Mono'=
;, Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; paddin=
g-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392=
157);">get_awaiter</code>, which is easier to write for the user, and also =
allows the possibility of Eric's proposal.</p><p style=3D"box-sizing: b=
order-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', H=
elvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px;=
line-height: 25.6px;"><br></p><h3 style=3D"box-sizing: border-box; line-he=
ight: 1.43; font-size: 1.5em; font-weight: bold; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif;"><a id=3D"user-content-case-study-1" class=3D"anchor"=
href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#case-study-1=
" aria-hidden=3D"true" style=3D"box-sizing: border-box; color: rgb(64, 120,=
192); position: absolute; top: 0px; left: 0px; display: block; padding-rig=
ht: 6px; padding-left: 30px; margin-left: -30px; line-height: 1.2; backgrou=
nd-color: transparent;"></a>Case Study</h3><p style=3D"box-sizing: border-b=
ox; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetic=
a, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-h=
eight: 25.6px;">Suppose you want to make a wrapper for any=C2=A0<em style=
=3D"box-sizing: border-box;">Awaiatable</em>=C2=A0that allows you to wait w=
ithout extracting the result, it could be implemented this way:</p><div cla=
ss=3D"highlight highlight-source-c++" style=3D"box-sizing: border-box; colo=
r: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, '=
Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 2=
5.6px;"><pre style=3D"box-sizing: border-box; overflow: auto; font-family: =
Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: =
13.6px; font-stretch: normal; line-height: 1.45; padding: 16px; border-radi=
us: 3px; word-wrap: normal; word-break: normal; background-color: rgb(247, =
247, 247);"><span class=3D"pl-k" style=3D"box-sizing: border-box; color: rg=
b(167, 29, 93);">template</span><<span class=3D"pl-k" style=3D"box-sizin=
g: border-box; color: rgb(167, 29, 93);">class</span> <span class=3D"pl-en"=
style=3D"box-sizing: border-box; color: rgb(121, 93, 163);">Task</span>>=
;
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">struct</span> <span class=3D"pl-en" style=3D"box-sizing: border-box; c=
olor: rgb(121, 93, 163);">ready_awaiter</span>
{
Task task;
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">bool</span> <span class=3D"pl-en" style=3D"box-sizing: border-box;=
color: rgb(121, 93, 163);">await_ready</span>()
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(16=
7, 29, 93);">return</span> <span class=3D"pl-c1" style=3D"box-sizing: borde=
r-box; color: rgb(0, 134, 179);">std::await_ready</span>(task);
}
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">template</span><<span class=3D"pl-k" style=3D"box-sizing: borde=
r-box; color: rgb(167, 29, 93);">class</span> <span class=3D"pl-en" style=
=3D"box-sizing: border-box; color: rgb(121, 93, 163);">F</span>>
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">auto</span> <span class=3D"pl-en" style=3D"box-sizing: border-box;=
color: rgb(121, 93, 163);">await_suspend</span>(F&& f)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(16=
7, 29, 93);">return</span> <span class=3D"pl-c1" style=3D"box-sizing: borde=
r-box; color: rgb(0, 134, 179);">std::await_suspend</span>(task, std::forwa=
rd<F>(f));
}
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">void</span> <span class=3D"pl-en" style=3D"box-sizing: border-box;=
color: rgb(121, 93, 163);">await_resume</span>() noexcept {}
};
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">template</span><<span class=3D"pl-k" style=3D"box-sizing: border-bo=
x; color: rgb(167, 29, 93);">class</span> <span class=3D"pl-en" style=3D"bo=
x-sizing: border-box; color: rgb(121, 93, 163);">Task</span>>
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">inline</span> ready_awaiter<Task> <span class=3D"pl-en" style=3D=
"box-sizing: border-box; color: rgb(121, 93, 163);">ready_impl</span>(Task&=
amp;& task)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> {std::forward<Task>(task)};
}
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">template</span><<span class=3D"pl-k" style=3D"box-sizing: border-bo=
x; color: rgb(167, 29, 93);">class</span> <span class=3D"pl-en" style=3D"bo=
x-sizing: border-box; color: rgb(121, 93, 163);">Task</span>>
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 9=
3);">inline</span> <span class=3D"pl-k" style=3D"box-sizing: border-box; co=
lor: rgb(167, 29, 93);">auto</span> <span class=3D"pl-en" style=3D"box-sizi=
ng: border-box; color: rgb(121, 93, 163);">ready</span>(Task&& task=
)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> <span class=3D"pl-c1" style=3D"box-sizing: border-bo=
x; color: rgb(0, 134, 179);">ready_impl</span>(<span class=3D"pl-c1" style=
=3D"box-sizing: border-box; color: rgb(0, 134, 179);">std::get_awaiter</spa=
n>(std::forward<Task>(task)));
}
....
<span class=3D"pl-c" style=3D"box-sizing: border-box; color: rgb(150, 152, =
150);">// usage</span>
await <span class=3D"pl-en" style=3D"box-sizing: border-box; color: rgb(121=
, 93, 163);">ready</span>(someAwaitable);</pre></div><h2 style=3D"box-sizin=
g: border-box; line-height: 1.225; font-size: 1.75em; font-weight: bold; pa=
dding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; =
border-bottom-color: rgb(238, 238, 238); color: rgb(51, 51, 51); font-famil=
y: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans=
, sans-serif;"><a id=3D"user-content-initialfinal_suspend---bool-or-awaiata=
ble" class=3D"anchor" href=3D"https://gist.github.com/jamboree/611b8c6551f8=
53956f7d#initialfinal_suspend---bool-or-awaiatable" aria-hidden=3D"true" st=
yle=3D"box-sizing: border-box; color: rgb(64, 120, 192); position: absolute=
; top: 0px; left: 0px; display: block; padding-right: 6px; padding-left: 30=
px; margin-left: -30px; line-height: 1; background-color: transparent;"></a=
><br>initial/final_suspend - bool or Awaiatable?</h2><p style=3D"box-sizing=
: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue'=
, Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16=
px; line-height: 25.6px;">I don't see why=C2=A0<code style=3D"box-sizin=
g: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Cou=
rier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2=
em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">initia=
l/final_suspend</code>=C2=A0needs to return=C2=A0<em style=3D"box-sizing: b=
order-box;">Awaiatable</em>.</p><p style=3D"box-sizing: border-box; color: =
rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Seg=
oe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6=
px;"><br></p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">If=C2=A0<code =
style=3D"box-sizing: border-box; font-family: Consolas, 'Liberation Mon=
o', Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; p=
adding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0=
..0392157);">initial/final_suspend</code>=C2=A0returns=C2=A0<code style=3D"b=
ox-sizing: border-box; font-family: Consolas, 'Liberation Mono', Me=
nlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bot=
tom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);=
">bool</code>, it's just like returning an=C2=A0<em style=3D"box-sizing=
: border-box;">Awaiatable</em>=C2=A0that onlys defines=C2=A0<code style=3D"=
box-sizing: border-box; font-family: Consolas, 'Liberation Mono', M=
enlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bo=
ttom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157)=
;">bool await_suspend</code>.</p><p style=3D"box-sizing: border-box; color:=
rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Se=
goe UI', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.=
6px;"><br></p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); f=
ont-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial,=
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">In the exampl=
e of=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, =
9;Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; paddi=
ng-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color:=
rgba(0, 0, 0, 0.0392157);">final_suspend</code>=C2=A0you shown, it's e=
xactly the same as the=C2=A0<code style=3D"box-sizing: border-box; font-fam=
ily: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-s=
ize: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px;=
background-color: rgba(0, 0, 0, 0.0392157);">bool</code>=C2=A0version. Wha=
t am I missing?</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 5=
1); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', A=
rial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><br></p>=
<p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: &#=
39;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, san=
s-serif; font-size: 16px; line-height: 25.6px;">On the other hand,=C2=A0<co=
de style=3D"box-sizing: border-box; font-family: Consolas, 'Liberation =
Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-top: 0.2em=
; padding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0, 0, 0=
, 0.0392157);">yield_value</code>=C2=A0does need to return=C2=A0<em style=
=3D"box-sizing: border-box;">Awaiatable</em>, I also reported it=C2=A0<a hr=
ef=3D"https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/zE=
MU_F-QcBo" style=3D"box-sizing: border-box; color: rgb(64, 120, 192); backg=
round-color: transparent;">here</a>.</p><p style=3D"box-sizing: border-box;=
color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, =
'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-heig=
ht: 25.6px;"><br></p><h2 style=3D"box-sizing: border-box; line-height: 1.22=
5; font-size: 1.75em; font-weight: bold; padding-bottom: 0.3em; border-bott=
om-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 23=
8, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Hel=
vetica, 'Segoe UI', Arial, freesans, sans-serif;"><a id=3D"user-con=
tent-syntax-to-specify-an-allocator" class=3D"anchor" href=3D"https://gist.=
github.com/jamboree/611b8c6551f853956f7d#syntax-to-specify-an-allocator" ar=
ia-hidden=3D"true" style=3D"box-sizing: border-box; color: rgb(64, 120, 192=
); position: absolute; top: 0px; left: 0px; display: block; padding-right: =
6px; padding-left: 30px; margin-left: -30px; line-height: 1; background-col=
or: transparent;"></a>Syntax to specify an allocator</h2><p style=3D"box-si=
zing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue&=
#39;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size=
: 16px; line-height: 25.6px;">A=C2=A0<code style=3D"box-sizing: border-box;=
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospac=
e; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0.2em; border-rad=
ius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">new</code>=C2=A0clau=
se can be used, for example:</p><div class=3D"highlight highlight-source-c+=
+" style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: &#=
39;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, san=
s-serif; font-size: 16px; line-height: 25.6px;"><pre style=3D"box-sizing: b=
order-box; overflow: auto; font-family: Consolas, 'Liberation Mono'=
, Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-=
height: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-br=
eak: normal; background-color: rgb(247, 247, 247);"><span class=3D"pl-k" st=
yle=3D"box-sizing: border-box; color: rgb(167, 29, 93);">template</span><=
;<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, =
93);">class</span> <span class=3D"pl-en" style=3D"box-sizing: border-box; c=
olor: rgb(121, 93, 163);">Allocator</span>>
std::future<<span class=3D"pl-k" style=3D"box-sizing: border-box; color:=
rgb(167, 29, 93);">void</span>> <span class=3D"pl-en" style=3D"box-sizi=
ng: border-box; color: rgb(121, 93, 163);">f</span>(Allocator alloc) new(al=
loc)
{
await ...
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">The is irrelev=
ant to how=C2=A0<code style=3D"box-sizing: border-box; font-family: Consola=
s, 'Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px;=
padding-top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-=
color: rgba(0, 0, 0, 0.0392157);">coroutine_traits</code>=C2=A0<em style=3D=
"box-sizing: border-box;">default</em>=C2=A0allocates, if the user specifie=
s=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, 'L=
iberation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-=
top: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color: rg=
ba(0, 0, 0, 0.0392157);">new(alloc)</code>, the=C2=A0<code style=3D"box-siz=
ing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, C=
ourier, monospace; font-size: 13.6px; padding-top: 0.2em; padding-bottom: 0=
..2em; border-radius: 3px; background-color: rgba(0, 0, 0, 0.0392157);">allo=
c</code>=C2=A0will override the default allocation strategy defined by=C2=
=A0<code style=3D"box-sizing: border-box; font-family: Consolas, 'Liber=
ation Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-top:=
0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color: rgba(0=
, 0, 0, 0.0392157);">coroutine_traits</code>.</p><p style=3D"box-sizing: bo=
rder-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', He=
lvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; =
line-height: 25.6px;"><br></p><h2 style=3D"box-sizing: border-box; line-hei=
ght: 1.225; font-size: 1.75em; font-weight: bold; padding-bottom: 0.3em; bo=
rder-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rg=
b(238, 238, 238); color: rgb(51, 51, 51); font-family: 'Helvetica Neue&=
#39;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif;"><a id=3D=
"user-content-auto-await-vs-resumableasync" class=3D"anchor" href=3D"https:=
//gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-vs-resumableasyn=
c" aria-hidden=3D"true" style=3D"box-sizing: border-box; color: rgb(64, 120=
, 192); position: absolute; top: 0px; left: 0px; display: block; padding-ri=
ght: 6px; padding-left: 30px; margin-left: -30px; line-height: 1; backgroun=
d-color: transparent;"></a>auto await v.s. resumable(async)</h2><p style=3D=
"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetic=
a Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; fo=
nt-size: 16px; line-height: 25.6px;">P0054R0 draws the idea "Automatic=
ally Awaited Awaitables", however, I think we'd better not to inte=
rfere with the type system. The original sample:</p><div class=3D"highlight=
highlight-source-c++" style=3D"box-sizing: border-box; color: rgb(51, 51, =
51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', =
Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><pre st=
yle=3D"box-sizing: border-box; overflow: auto; font-family: Consolas, '=
Liberation Mono', Menlo, Courier, monospace; font-size: 13.6px; font-st=
retch: normal; line-height: 1.45; padding: 16px; border-radius: 3px; word-w=
rap: normal; word-break: normal; background-color: rgb(247, 247, 247);"><sp=
an class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 93);=
">auto</span> MyProxy::<span class=3D"pl-k" style=3D"box-sizing: border-box=
; color: rgb(167, 29, 93);">operator</span>=3D(<span class=3D"pl-k" style=
=3D"box-sizing: border-box; color: rgb(167, 29, 93);">int</span> output)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">struct</span> <span class=3D"pl-en" style=3D"box-sizing: border-bo=
x; color: rgb(121, 93, 163);">Awaitable</span> <span class=3D"pl-k" style=
=3D"box-sizing: border-box; color: rgb(167, 29, 93);">auto</span> await { .=
... };
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> Awaitable{...};
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">could be writt=
en this way:</p><div class=3D"highlight highlight-source-c++" style=3D"box-=
sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neu=
e', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-si=
ze: 16px; line-height: 25.6px;"><pre style=3D"box-sizing: border-box; overf=
low: auto; font-family: Consolas, 'Liberation Mono', Menlo, Courier=
, monospace; font-size: 13.6px; font-stretch: normal; line-height: 1.45; pa=
dding: 16px; border-radius: 3px; word-wrap: normal; word-break: normal; bac=
kground-color: rgb(247, 247, 247);">await <span class=3D"pl-k" style=3D"box=
-sizing: border-box; color: rgb(167, 29, 93);">auto</span> MyProxy::<span c=
lass=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">op=
erator</span>=3D(<span class=3D"pl-k" style=3D"box-sizing: border-box; colo=
r: rgb(167, 29, 93);">int</span> output)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">struct</span> <span class=3D"pl-en" style=3D"box-sizing: border-bo=
x; color: rgb(121, 93, 163);">Awaitable</span> { ... };
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> Awaitable{...};
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">Note that the=
=C2=A0<code style=3D"box-sizing: border-box; font-family: Consolas, 'Li=
beration Mono', Menlo, Courier, monospace; font-size: 13.6px; padding-t=
op: 0.2em; padding-bottom: 0.2em; border-radius: 3px; background-color: rgb=
a(0, 0, 0, 0.0392157);">await</code>=C2=A0prefix is not part of the type sy=
stem here, it just instructs the compiler to await on what it returns.</p><=
p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: =
9;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans=
-serif; font-size: 16px; line-height: 25.6px;"><br></p><p style=3D"box-sizi=
ng: border-box; color: rgb(51, 51, 51); font-family: 'Helvetica Neue=
9;, Helvetica, 'Segoe UI', Arial, freesans, sans-serif; font-size: =
16px; line-height: 25.6px;">That said, the "auto await" idea is n=
ot flexible enough, consider the special functions, e.g. constructors &=
destructors, which could also be resumable in theory, there's no way f=
or them to use "auto await".</p><p style=3D"box-sizing: border-bo=
x; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica=
, 'Segoe UI', Arial, freesans, sans-serif; font-size: 16px; line-he=
ight: 25.6px;"><br></p><p style=3D"box-sizing: border-box; color: rgb(51, 5=
1, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI'=
;, Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;">A be=
tter solution is to consider something like the approach taken by Resumable=
Expressions (P0114R0).</p><p style=3D"box-sizing: border-box; color: rgb(5=
1, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI=
', Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;">=
<br></p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-fa=
mily: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, frees=
ans, sans-serif; font-size: 16px; line-height: 25.6px;">I had a draft descr=
ibing the joint idea:=C2=A0<a href=3D"https://gist.github.com/jamboree/a2b3=
fe32eeb8c21e820c" style=3D"box-sizing: border-box; color: rgb(64, 120, 192)=
; background-color: transparent;">https://gist.github.com/jamboree/a2b3fe32=
eeb8c21e820c</a></p><p style=3D"box-sizing: border-box; color: rgb(51, 51, =
51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', =
Arial, freesans, sans-serif; font-size: 16px; line-height: 25.6px;"><br></p=
><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: &=
#39;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sa=
ns-serif; font-size: 16px; line-height: 25.6px;">The same example written i=
n the draft will look like:</p><div class=3D"highlight highlight-source-c++=
" style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: =
9;Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans=
-serif; font-size: 16px; line-height: 25.6px;"><pre style=3D"box-sizing: bo=
rder-box; overflow: auto; font-family: Consolas, 'Liberation Mono',=
Menlo, Courier, monospace; font-size: 13.6px; font-stretch: normal; line-h=
eight: 1.45; padding: 16px; border-radius: 3px; word-wrap: normal; word-bre=
ak: normal; background-color: rgb(247, 247, 247);">async <span class=3D"pl-=
k" style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">auto</span> M=
yProxy::<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(16=
7, 29, 93);">operator</span>=3D(<span class=3D"pl-k" style=3D"box-sizing: b=
order-box; color: rgb(167, 29, 93);">int</span> output)
{
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">struct</span> <span class=3D"pl-en" style=3D"box-sizing: border-bo=
x; color: rgb(121, 93, 163);">Awaitable</span> { ... };
<span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 2=
9, 93);">return</span> await Awaitable{...};
}</pre></div><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); fo=
nt-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, =
freesans, sans-serif; font-size: 16px; line-height: 25.6px;">The most inter=
esting part of the draft is "Context-based overloading", which I =
haven't seen in other proposals, I'd like to get some feedback from=
you.</p><p style=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-f=
amily: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, free=
sans, sans-serif; font-size: 16px; line-height: 25.6px;"><br></p><p style=
=3D"box-sizing: border-box; color: rgb(51, 51, 51); font-family: 'Helve=
tica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif;=
font-size: 16px; line-height: 25.6px;">Thanks.</p></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_7608_1887856342.1444228468369--
------=_Part_7607_1893098870.1444228468367--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Wed, 7 Oct 2015 09:04:16 -0700 (PDT)
Raw View
------=_Part_1554_1679004451.1444233856249
Content-Type: multipart/alternative;
boundary="----=_Part_1555_27641560.1444233856250"
------=_Part_1555_27641560.1444233856250
Content-Type: text/plain; charset=UTF-8
Hi Tongari:
Thank you for constructive comments. I love those :-) .
I need some time to think about the ideas you expressed before I can
comment on them properly.
A few quick things I can answer immediately.
RAII: Consider cases of non-owning use of coroutine_handle, such as
illustrated in http://wg21.link/P0055. Since coroutine_handle is a compiler
magic type, we need to be careful of not adding too much semantics to it
and leave considerations like RAII to the library. You can trivially write
safe_coroutine_handle that has the properties you desire.
resume/suspend - see the await_transform in http://wg21.link/P0054. Would
it allow you to solve the use case that you were thinking about.
initial_suspend/final_suspend - First section of http://wg21.link/P0054 goes
into details explaining why bool won't work.
More later.
--
---
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_1555_27641560.1444233856250
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi Tongari:</div><div><br></div><div>Thank you for co=
nstructive comments. I love those :-) .</div><div>I need some time to think=
about the ideas you expressed before I can comment on them properly.</div>=
<div><br></div><div>A few quick things I can answer immediately.</div><div>=
<br>RAII: Consider cases of non-owning use of coroutine_handle, such as ill=
ustrated in <a href=3D"http://wg21.link/P0055">http://wg21.link/P0055</a>. =
Since coroutine_handle is a compiler magic type, we need to be careful of n=
ot adding too much semantics to it and leave considerations like RAII to th=
e library. You can trivially write safe_coroutine_handle that has the prope=
rties you desire. </div><div><br></div><div>resume/suspend - see the await_=
transform in <a href=3D"http://wg21.link/P0054">http://wg21.link/P0054</a>.=
Would it allow you to solve the use case that you were thinking about.</di=
v><div><br></div><div>initial_suspend/final_suspend - First section of <a h=
ref=3D"http://wg21.link/P0054">http://wg21.link/P0054</a>=C2=A0goes into de=
tails explaining why bool won't work.</div><div><br></div><div>More lat=
er.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1555_27641560.1444233856250--
------=_Part_1554_1679004451.1444233856249--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 9 Oct 2015 18:07:01 -0700 (PDT)
Raw View
------=_Part_3359_266172057.1444439222184
Content-Type: multipart/alternative;
boundary="----=_Part_3360_21453311.1444439222184"
------=_Part_3360_21453311.1444439222184
Content-Type: text/plain; charset=UTF-8
Continued:
1. Customization points:
Coroutines proposal have not been looked by LEWG, so I expect that part to
be modified as needed according to the LEWG preferences. If they like
Eric's approach, that's what it will be. I have no objections.
2. return moveOnly:
I agree, the behavior should much ordinary function. I will tweak the
wording to fit it in.
3. unwind
One of the idea that was suggested recently was to make return_value return
awaitable. That way, the consumer can directly access the value from the
expression without copy/move into the promise. In that case, there is
definitely no unwind at the point of return <expr>. I think the efficiency
gains outweigh the consideration you mentioned.
4. syntax for allocator
I don't mind. There were other suggestions like adding
using(traits/promise) at the same position, so that you not only can
control the allocator, but, the entire machinery. I think those a valuable
ideas to explore in the future. At the moment, I am looking for things to
cut :-) . I would have cut yield, but, it only saves a paragraph or two in
the wording and implementation is just await $p.yield_value(expr).
5. automatically awaited awaitables and your proposal on the github
I have concerns about magically injecting suspend points and turning
functions into coroutines and vice versa. I think there are ways to evolve
the coroutines in that direction in the future, but, I am not sure it is a
good idea.
As I said. At the moment I am trying to keep proposal to the minimally
useful size. C++17 is very close. Let's get something efficient and useful
and grow it in the future as needed.
Cheers,
Gor
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3360_21453311.1444439222184
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Continued:</div><div><br></div><div>1. Customization =
points:</div><div><br></div><div>Coroutines proposal have not been looked b=
y LEWG, so I expect that part to be=C2=A0modified as needed=C2=A0according =
to the LEWG preferences. If they like Eric's approach, that's what =
it will be. I have no objections.</div><div><br></div><div>2. return moveOn=
ly:</div><div><br></div><div>I agree, the behavior should much ordinary fun=
ction. I will tweak the wording to fit it in.</div><div><br></div><div>3. u=
nwind</div><div><br></div><div>One of the idea that was suggested recently =
was to make return_value return awaitable. That way, the consumer can direc=
tly access the value from the expression without copy/move into the promise=
.. In that case, there is definitely no unwind at the point of return <ex=
pr>. I=C2=A0think the efficiency gains outweigh the consideration you me=
ntioned.</div><div><br></div><div>4. syntax for allocator</div><div><br></d=
iv><div>I don't mind. There were other suggestions like adding using(tr=
aits/promise) at the same position, so that you not only can control the al=
locator, but, the entire machinery. I think those a valuable ideas to explo=
re in the future. At the moment, I am looking for things to cut :-) . I wou=
ld have cut yield, but, it only saves a paragraph or two in the wording and=
implementation is just await $p.yield_value(expr).</div><div><br></div><di=
v>5. automatically awaited awaitables and your proposal on the github</div>=
<div><br></div><div>I have concerns about magically injecting=C2=A0suspend =
points and turning functions into coroutines and vice versa. I think there =
are ways to evolve the coroutines in that direction in the future, but, I a=
m not sure it is a good idea.</div><div><br></div><div>As I said. At the mo=
ment I am trying to keep proposal to the minimally useful size. C++17 is ve=
ry close. Let's get something efficient and useful and grow it in the f=
uture as needed.</div><div><br></div><div>Cheers,</div><div>Gor</div><div><=
br></div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3360_21453311.1444439222184--
------=_Part_3359_266172057.1444439222184--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Fri, 9 Oct 2015 18:10:24 -0700 (PDT)
Raw View
------=_Part_3450_718749323.1444439424741
Content-Type: multipart/alternative;
boundary="----=_Part_3451_1393606080.1444439424746"
------=_Part_3451_1393606080.1444439424746
Content-Type: text/plain; charset=UTF-8
much => match
> I agree, the behavior should *match *much ordinary function.
>
--
---
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_3451_1393606080.1444439424746
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div>much =3D> match=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr"><div>I agree, the behavior should <strong>match </strong><font col=
or=3D"#ff0000">much </font>ordinary function.<br></div></div></blockquote>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3451_1393606080.1444439424746--
------=_Part_3450_718749323.1444439424741--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Sat, 10 Oct 2015 16:08:54 +0800
Raw View
--001a113fb33a7affa70521bb9b56
Content-Type: text/plain; charset=UTF-8
Hi Gor,
<https://gist.github.com/jamboree/611b8c6551f853956f7d#raii>RAII
I've read P0055 as well, but I don't see what non-owning cases you
mentioned, could you elaborate?
Note that my suggestion is not groundless - I have a small wrapper library
act <https://github.com/jamboree/act> for ASIO, which is the base of the
Network proposal, and it works well with my CO2 library, which exposed
unique-semantic for coroutine. It's implementable with my
preprocessor-based emulation, I don't believe the same cannot be
implemented in the language itself.
Surely you can have something like safe_coroutine_handle, but you're
missing the important feature to interact with the coroutine.
Without RAII, the await_suspend looks like:
bool await_suspend(coroutine_handle<Promise> coro); // by value
With unique-semantic, it looks like:
bool await_suspend(coroutine<Promise>& coro); // by reference
The coro is taken by reference, so it can *transfer* the ownership of the
coroutine. If the coroutine is not transferred but is suspended, the caller
still owns the coroutine and can safely unwind the stack, it's impossible
without RAII at the first place.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#resumesuspend>
resume/suspend
I think their purpose is different from await_transform, they're desgined
for RAII to complement unique-semantic in some cases.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#initial_suspendfinal_suspend>
initial_suspend/final_suspend
I can't understand the rationale, I think the example of final_suspend you
shown is exactly the same as the bool version, what's the difference?
<https://gist.github.com/jamboree/611b8c6551f853956f7d#customization-points>Customization
points
Even if the LEWG doesn't consider Eric's approach, you should still make
those customization points available as free functions like std::begin,
std::end, etc.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#unwind>unwind
I don't understand the benefit of making it return Awaitable, any example?
Anyway, I think you can still unwind the stack before return_value as long
as you store the value somewhere before unwinding the stack.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>auto
await alternatives
Another benefit of resumable/async (whatever the mark is called) approach
is that you don't need to have await and yield as keywords, instead, they
could be free functions std::await andstd::yield. In the standard, you can
define 2 pseudo keywords __await and __yield and their semantic, the
implementation doesn't need to provide them, but the std::await and
std::yield can be defined in terms of __await and __yield respectively:
template<Awaitable T>
async decltype(auto) await(T&& t)
{
return __await forward<T>(t);
}
template<class T>
async decltype(auto) yield(T&& t)
{
return __yield forward<T>(t);
}
It'd be nice if we could have coroutine in C++17, but it'll be much harder
to fix it afterwards considering the backward-compatibility. We'd better
make the consideration thorough and not in a rush.
Thanks.
--
---
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/.
--001a113fb33a7affa70521bb9b56
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><p style=3D"margin-bottom:16px;=
color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Seg=
oe UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px;marg=
in-top:0px!important">Hi Gor,</p><h2 style=3D"margin-top:1em;margin-bottom:=
16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-=
width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);co=
lor:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe=
UI',Arial,freesans,sans-serif"><a id=3D"user-content-raii" class=3D"" =
href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#raii" style=
=3D"color:rgb(64,120,192);text-decoration:none;display:block;padding-right:=
6px;padding-left:30px;line-height:1;background-color:transparent"></a>RAII<=
/h2><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-=
family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans=
,sans-serif;font-size:16px;line-height:25.6px">I've read P0055 as well,=
but I don't see what non-owning cases you mentioned, could you elabora=
te?</p><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);fo=
nt-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,frees=
ans,sans-serif;font-size:16px;line-height:25.6px">Note that my suggestion i=
s not groundless - I have a small wrapper library=C2=A0<a href=3D"https://g=
ithub.com/jamboree/act" style=3D"color:rgb(64,120,192);text-decoration:none=
;background-color:transparent">act</a>=C2=A0for ASIO, which is the base of =
the Network proposal, and it works well with my CO2 library, which exposed =
unique-semantic for coroutine. It's implementable with my preprocessor-=
based emulation, I don't believe the same cannot be implemented in the =
language itself.</p><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb=
(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI'=
;,Arial,freesans,sans-serif;font-size:16px;line-height:25.6px">Surely you c=
an have something like=C2=A0<code style=3D"font-family:Consolas,'Libera=
tion Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;m=
argin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">safe_co=
routine_handle</code>, but you're missing the important feature to inte=
ract with the coroutine.</p><p style=3D"margin-top:0px;margin-bottom:16px;c=
olor:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Sego=
e UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px">With=
out RAII, the=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono=
',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px=
;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">await_suspend</c=
ode>=C2=A0looks like:</p><div class=3D"" style=3D"margin-bottom:16px;color:=
rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI&=
#39;,Arial,freesans,sans-serif;font-size:16px;line-height:25.6px"><pre styl=
e=3D"overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Cou=
rier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stret=
ch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:normal;=
background-color:rgb(247,247,247)"><span class=3D"" style=3D"color:rgb(167,=
29,93)">bool</span> <span class=3D"" style=3D"color:rgb(121,93,163)">await_=
suspend</span>(coroutine_handle<Promise> coro); <span class=3D"" styl=
e=3D"color:rgb(150,152,150)">// by value</span></pre></div><p style=3D"marg=
in-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetic=
a Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-siz=
e:16px;line-height:25.6px">With unique-semantic, it looks like:</p><div cla=
ss=3D"" style=3D"margin-bottom:16px;color:rgb(51,51,51);font-family:'He=
lvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;fo=
nt-size:16px;line-height:25.6px"><pre style=3D"overflow:auto;font-family:Co=
nsolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;m=
argin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;paddin=
g:16px;border-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)=
"><span class=3D"" style=3D"color:rgb(167,29,93)">bool</span> <span class=
=3D"" style=3D"color:rgb(121,93,163)">await_suspend</span>(coroutine<Pro=
mise>& coro); <span class=3D"" style=3D"color:rgb(150,152,150)">// b=
y reference</span></pre></div><p style=3D"margin-top:0px;margin-bottom:16px=
;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Se=
goe UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px">Th=
e=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono',Menlo,=
Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radi=
us:3px;background-color:rgba(0,0,0,0.0392157)">coro</code>=C2=A0is taken by=
reference, so it can=C2=A0<em>transfer</em>=C2=A0the ownership of the coro=
utine. If the coroutine is not transferred but is suspended, the caller sti=
ll owns the coroutine and can safely unwind the stack, it's impossible =
without RAII at the first place.</p><h2 style=3D"margin-top:1em;margin-bott=
om:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bott=
om-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)=
;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Se=
goe UI',Arial,freesans,sans-serif"><a id=3D"user-content-resumesuspend"=
class=3D"" href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#r=
esumesuspend" style=3D"color:rgb(64,120,192);text-decoration:none;display:b=
lock;padding-right:6px;padding-left:30px;line-height:1;background-color:tra=
nsparent"></a>resume/suspend</h2><p style=3D"margin-top:0px;margin-bottom:1=
6px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'=
;Segoe UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px"=
>I think their purpose is different from=C2=A0<code style=3D"font-family:Co=
nsolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;p=
adding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0=
..0392157)">await_transform</code>, they're desgined for RAII to complem=
ent unique-semantic in some cases.</p><h2 style=3D"margin-top:1em;margin-bo=
ttom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bo=
ttom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,23=
8);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'=
Segoe UI',Arial,freesans,sans-serif"><a id=3D"user-content-initial_susp=
endfinal_suspend" class=3D"" href=3D"https://gist.github.com/jamboree/611b8=
c6551f853956f7d#initial_suspendfinal_suspend" style=3D"color:rgb(64,120,192=
);text-decoration:none;display:block;padding-right:6px;padding-left:30px;li=
ne-height:1;background-color:transparent"></a>initial_suspend/final_suspend=
</h2><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font=
-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesan=
s,sans-serif;font-size:16px;line-height:25.6px">I can't understand the =
rationale, I think the example of final_suspend you shown is exactly the sa=
me as the bool version, what's the difference?</p><h2 style=3D"margin-t=
op:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom=
:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-colo=
r:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue'=
,Helvetica,'Segoe UI',Arial,freesans,sans-serif"><a id=3D"user-cont=
ent-customization-points" class=3D"" href=3D"https://gist.github.com/jambor=
ee/611b8c6551f853956f7d#customization-points" style=3D"color:rgb(64,120,192=
);text-decoration:none;display:block;padding-right:6px;padding-left:30px;li=
ne-height:1;background-color:transparent"></a>Customization points</h2><p s=
tyle=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&=
#39;Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-se=
rif;font-size:16px;line-height:25.6px">Even if the LEWG doesn't conside=
r Eric's approach, you should still make those customization points ava=
ilable as free functions like=C2=A0<code style=3D"font-family:Consolas,'=
;Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2e=
m 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">=
std::begin</code>,=C2=A0<code style=3D"font-family:Consolas,'Liberation=
Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margi=
n:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">std::end</c=
ode>, etc.</p><h2 style=3D"margin-top:1em;margin-bottom:16px;line-height:1.=
225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bo=
ttom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);f=
ont-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,free=
sans,sans-serif"><a id=3D"user-content-unwind" class=3D"" href=3D"https://g=
ist.github.com/jamboree/611b8c6551f853956f7d#unwind" style=3D"color:rgb(64,=
120,192);text-decoration:none;display:block;padding-right:6px;padding-left:=
30px;line-height:1;background-color:transparent"></a>unwind</h2><p style=3D=
"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Hel=
vetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;fon=
t-size:16px;line-height:25.6px">I don't understand the benefit of makin=
g it return Awaitable, any example? Anyway, I think you can still unwind th=
e stack before=C2=A0<code style=3D"font-family:Consolas,'Liberation Mon=
o',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0p=
x;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">return_value</c=
ode>=C2=A0as long as you store the value somewhere before unwinding the sta=
ck.</p><h2 style=3D"margin-top:1em;margin-bottom:16px;line-height:1.225;fon=
t-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-st=
yle:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-fam=
ily:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sa=
ns-serif"><a id=3D"user-content-auto-await-alternatives" class=3D"" href=3D=
"https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternati=
ves" style=3D"color:rgb(64,120,192);text-decoration:none;display:block;padd=
ing-right:6px;padding-left:30px;line-height:1;background-color:transparent"=
></a>auto await alternatives</h2><p style=3D"margin-top:0px;margin-bottom:1=
6px;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'=
;Segoe UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px"=
>Another benefit of resumable/async (whatever the mark is called) approach =
is that you don't need to have=C2=A0<code style=3D"font-family:Consolas=
,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding=
:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.03921=
57)">await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Li=
beration Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0=
px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">yie=
ld</code>=C2=A0as keywords, instead, they could be free functions=C2=A0<cod=
e style=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,mon=
ospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;back=
ground-color:rgba(0,0,0,0.0392157)">std::await</code>=C2=A0and<code style=
=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;=
font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-=
color:rgba(0,0,0,0.0392157)">std::yield</code>. In the standard, you can de=
fine 2 pseudo keywords=C2=A0<code style=3D"font-family:Consolas,'Libera=
tion Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;m=
argin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">__await=
</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Liberation M=
ono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:=
0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">__yield</code=
>=C2=A0and their semantic, the implementation doesn't need to provide t=
hem, but the=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono&=
#39;,Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;=
border-radius:3px;background-color:rgba(0,0,0,0.0392157)">std::await</code>=
=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono'=
;,Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;bor=
der-radius:3px;background-color:rgba(0,0,0,0.0392157)">std::yield</code>=C2=
=A0can be defined in terms of=C2=A0<code style=3D"font-family:Consolas,'=
;Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2e=
m 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">=
__await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Liber=
ation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;=
margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">__yiel=
d</code>=C2=A0respectively:</p><div class=3D"" style=3D"margin-bottom:16px;=
color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Seg=
oe UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px"><pr=
e style=3D"overflow:auto;font-family:Consolas,'Liberation Mono',Men=
lo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font=
-stretch:normal;line-height:1.45;padding:16px;border-radius:3px;word-wrap:n=
ormal;background-color:rgb(247,247,247)"><span class=3D"" style=3D"color:rg=
b(167,29,93)">template</span><Awaitable T>
async <span class=3D"" style=3D"color:rgb(121,93,163)">decltype</span>(<spa=
n class=3D"" style=3D"color:rgb(167,29,93)">auto</span>) await(T&& =
t)
{
<span class=3D"" style=3D"color:rgb(167,29,93)">return</span> __await f=
orward<T>(t);
}
<span class=3D"" style=3D"color:rgb(167,29,93)">template</span><<span cl=
ass=3D"" style=3D"color:rgb(167,29,93)">class</span> <span class=3D"" style=
=3D"color:rgb(121,93,163)">T</span>>
async <span class=3D"" style=3D"color:rgb(121,93,163)">decltype</span>(<spa=
n class=3D"" style=3D"color:rgb(167,29,93)">auto</span>) yield(T&& =
t)
{
<span class=3D"" style=3D"color:rgb(167,29,93)">return</span> __yield f=
orward<T>(t);
}</pre></div><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,=
51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial=
,freesans,sans-serif;font-size:16px;line-height:25.6px"><br></p><p style=3D=
"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Hel=
vetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;fon=
t-size:16px;line-height:25.6px">It'd be nice if we could have coroutine=
in C++17, but it'll be much harder to fix it afterwards considering th=
e backward-compatibility. We'd better make the consideration thorough a=
nd not in a rush.</p><p style=3D"margin-top:0px;color:rgb(51,51,51);font-fa=
mily:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,s=
ans-serif;font-size:16px;line-height:25.6px;margin-bottom:0px!important">Th=
anks.</p></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113fb33a7affa70521bb9b56--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 10 Oct 2015 06:51:50 -0700 (PDT)
Raw View
------=_Part_400_1763072859.1444485110309
Content-Type: multipart/alternative;
boundary="----=_Part_401_461332557.1444485110310"
------=_Part_401_461332557.1444485110310
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 4:08:56 AM UTC-4, TONGARI J wrote:
>
> Hi Gor,
> <https://gist.github.com/jamboree/611b8c6551f853956f7d#raii>RAII
>
> I've read P0055 as well, but I don't see what non-owning cases you
> mentioned, could you elaborate?
>
> Note that my suggestion is not groundless - I have a small wrapper library
> act <https://github.com/jamboree/act> for ASIO, which is the base of the
> Network proposal, and it works well with my CO2 library, which exposed
> unique-semantic for coroutine. It's implementable with my
> preprocessor-based emulation, I don't believe the same cannot be
> implemented in the language itself.
>
> Surely you can have something like safe_coroutine_handle, but you're
> missing the important feature to interact with the coroutine.
>
> Without RAII, the await_suspend looks like:
>
> bool await_suspend(coroutine_handle<Promise> coro); // by value
>
> With unique-semantic, it looks like:
>
> bool await_suspend(coroutine<Promise>& coro); // by reference
>
> The coro is taken by reference, so it can *transfer* the ownership of the
> coroutine. If the coroutine is not transferred but is suspended, the caller
> still owns the coroutine and can safely unwind the stack, it's impossible
> without RAII at the first place.
>
This is a bit confusing, so I want to explain how I understand things.
`await_suspend` is called by `await`. It is called on `e`, which is the
evaluation of `operator await` on `await`'s expression. So the function
call is `e.await_suspend`. It is given a coroutine handle that is the
coroutine for *the current function*, not the coroutine that was just
called. So `await_suspend` tells the promise object (converted by `operator
await`) to suspend the current function.
Given all of that, if you were to transfer ownership of the current
function's coroutine handle to the promise object, that would mean:
1) The current function actually *has ownership of itself* (you can't
transfer ownership if you don't own something).
2) The coroutine promise from the `await`ing expression will own the
current function now.
#1 does not make sense. The owner of a coroutine is the *caller*, not the
function itself (things can't own themselves uniquely). The caller has the
right to destroy the coroutine when it is suspended, and there is no reason
to deny the caller that right (for example, if the caller throws an
exception).
And I'm just not sure of the point of #2. Why do you want to give the
coroutine promise that was just called ownership of the function that
called it?
Now P0057 is a complex proposal, so I may be misunderstanding what you and
they are talking about. But from my limited comprehension of it, it seems
like you're performing an action that doesn't make sense.
Then again, I'm not sure why the `operator await` class from the promise
being waited on is being told to suspend the function that called it. But
to the extent that this operation makes sense, that operation clearly
should not transfer ownership.
Though I did find something highly disconcerting. I see a lot of code
taking `coroutine_handle<>` by value. Since they take the parameter by
value, that strongly suggests *slicing* (copying of the base class). Maybe
that's OK, but I think it would be clearer if they took them by reference
or something.
> resume/suspend
>
> I think their purpose is different from await_transform, they're desgined
> for RAII to complement unique-semantic in some cases.
>
> <https://gist.github.com/jamboree/611b8c6551f853956f7d#initial_suspendfinal_suspend>
> initial_suspend/final_suspend
>
> I can't understand the rationale, I think the example of final_suspend you
> shown is exactly the same as the bool version, what's the difference?
>
P0054 explained exactly why the bool version doesn't work, with specific
cases. It is complex, but the general gist is that there are race
conditions with threaded coroutine scheduling that make a `bool`-only
version non-functional.
>
> <https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>auto
> await alternatives
>
> Another benefit of resumable/async (whatever the mark is called) approach
> is that you don't need to have await and yield as keywords, instead, they
> could be free functions std::await andstd::yield. In the standard, you
> can define 2 pseudo keywords __await and __yield and their semantic, the
> implementation doesn't need to provide them, but the std::await and
> std::yield can be defined in terms of __await and __yield respectively:
>
What are "pseudo keywords"? More importantly, you can't make keywords (or
any such semantic) with double-underscores. That is explicitly reserved for
*implementation* use, not standard use.
Also, we shouldn't be judging a proposal to be better solely because it
uses fewer keywords. We've got too many proposals in the pipe that need
genuine keywords to avoid adopting P0056 (soft keywords). At which point,
what is and isn't a keyword essentially becomes irrelevant.
If the committee rejects P0056, then an approach like the one you suggested
could be adopted. But that really ought to be something that gets dealt
with once we're sure we have the functionality behaving correctly.
--
---
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_401_461332557.1444485110310
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, October 10, 2015 at 4:08:56 AM UTC-4, TONGARI J wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><p style=
=3D"margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue&=
#39;,Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;=
line-height:25.6px;margin-top:0px!important">Hi Gor,</p><h2 style=3D"margin=
-top:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bott=
om:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-co=
lor:rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue=
9;,Helvetica,'Segoe UI',Arial,freesans,sans-serif"><a href=3D"https=
://gist.github.com/jamboree/611b8c6551f853956f7d#raii" style=3D"color:rgb(6=
4,120,192);text-decoration:none;display:block;padding-right:6px;padding-lef=
t:30px;line-height:1;background-color:transparent" target=3D"_blank" rel=3D=
"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url?q\75h=
ttps%3A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23raii\46sa\=
75D\46sntz\0751\46usg\75AFQjCNFRGmSoa3jITr9clgyk2GQcb8UDEg';return true=
;" onclick=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2=
Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23raii\46sa\75D\46sntz\0=
751\46usg\75AFQjCNFRGmSoa3jITr9clgyk2GQcb8UDEg';return true;"></a>RAII<=
/h2><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-=
family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans=
,sans-serif;font-size:16px;line-height:25.6px">I've read P0055 as well,=
but I don't see what non-owning cases you mentioned, could you elabora=
te?</p><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);fo=
nt-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,frees=
ans,sans-serif;font-size:16px;line-height:25.6px">Note that my suggestion i=
s not groundless - I have a small wrapper library=C2=A0<a href=3D"https://g=
ithub.com/jamboree/act" style=3D"color:rgb(64,120,192);text-decoration:none=
;background-color:transparent" target=3D"_blank" rel=3D"nofollow" onmousedo=
wn=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2Fgithub.=
com%2Fjamboree%2Fact\46sa\75D\46sntz\0751\46usg\75AFQjCNGK4Lo2lo548Mu_H-m5Z=
JTol0XTJw';return true;" onclick=3D"this.href=3D'https://www.google=
..com/url?q\75https%3A%2F%2Fgithub.com%2Fjamboree%2Fact\46sa\75D\46sntz\0751=
\46usg\75AFQjCNGK4Lo2lo548Mu_H-m5ZJTol0XTJw';return true;">act</a>=C2=
=A0for ASIO, which is the base of the Network proposal, and it works well w=
ith my CO2 library, which exposed unique-semantic for coroutine. It's i=
mplementable with my preprocessor-based emulation, I don't believe the =
same cannot be implemented in the language itself.</p><p style=3D"margin-to=
p:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neu=
e',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16p=
x;line-height:25.6px">Surely you can have something like=C2=A0<code style=
=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;=
font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-=
color:rgba(0,0,0,0.0392157)">safe_coroutine_handle</code>, but you're m=
issing the important feature to interact with the coroutine.</p><p style=3D=
"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Hel=
vetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;fon=
t-size:16px;line-height:25.6px">Without RAII, the=C2=A0<code style=3D"font-=
family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size=
:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgb=
a(0,0,0,0.0392157)">await_suspend</code>=C2=A0looks like:</p><div style=3D"=
margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue'=
,Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;line=
-height:25.6px"><pre style=3D"overflow:auto;font-family:Consolas,'Liber=
ation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;mar=
gin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;border-rad=
ius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span style=3D"=
color:rgb(167,29,93)">bool</span> <span style=3D"color:rgb(121,93,163)">awa=
it_suspend</span>(coroutine_<wbr>handle<Promise> coro); <span style=
=3D"color:rgb(150,152,150)">// by value</span></pre></div><p style=3D"margi=
n-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica=
Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size=
:16px;line-height:25.6px">With unique-semantic, it looks like:</p><div styl=
e=3D"margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue=
',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px=
;line-height:25.6px"><pre style=3D"overflow:auto;font-family:Consolas,'=
Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;margin-top:0p=
x;margin-bottom:0px;font-stretch:normal;line-height:1.45;padding:16px;borde=
r-radius:3px;word-wrap:normal;background-color:rgb(247,247,247)"><span styl=
e=3D"color:rgb(167,29,93)">bool</span> <span style=3D"color:rgb(121,93,163)=
">await_suspend</span>(coroutine<<wbr>Promise>& coro); <span styl=
e=3D"color:rgb(150,152,150)">// by reference</span></pre></div><p style=3D"=
margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helv=
etica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font=
-size:16px;line-height:25.6px">The=C2=A0<code style=3D"font-family:Consolas=
,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding=
:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.03921=
57)">coro</code>=C2=A0is taken by reference, so it can=C2=A0<i>transfer</i>=
=C2=A0the ownership of the coroutine. If the coroutine is not transferred b=
ut is suspended, the caller still owns the coroutine and can safely unwind =
the stack, it's impossible without RAII at the first place.</p></div></=
div></blockquote><div>This is a bit confusing, so I want to explain how I u=
nderstand things.<br><br>`await_suspend` is called by `await`. It is called=
on `e`, which is the evaluation of `operator await` on `await`'s expre=
ssion. So the function call is `e.await_suspend`. It is given a coroutine h=
andle that is the coroutine for <i>the current function</i>, not the corout=
ine that was just called. So `await_suspend` tells the promise object (conv=
erted by `operator await`) to suspend the current function.<br><br>Given al=
l of that, if you were to transfer ownership of the current function's =
coroutine handle to the promise object, that would mean:<br><br>1) The curr=
ent function actually <i>has ownership of itself</i> (you can't transfe=
r ownership if you don't own something).<br><br>2) The coroutine promis=
e from the `await`ing expression will own the current function now.<br><br>=
#1 does not make sense. The owner of a coroutine is the <i>caller</i>, not =
the function itself (things can't own themselves uniquely). The caller =
has the right to destroy the coroutine when it is suspended, and there is n=
o reason to deny the caller that right (for example, if the caller throws a=
n exception).<br><br>And I'm just not sure of the point of #2. Why do y=
ou want to give the coroutine promise that was just called ownership of the=
function that called it?<br><br>Now P0057 is a complex proposal, so I may =
be misunderstanding what you and they are talking about. But from my limite=
d comprehension of it, it seems like you're performing an action that d=
oesn't make sense.<br><br>Then again, I'm not sure why the `operato=
r await` class from the promise being waited on is being told to suspend th=
e function that called it. But to the extent that this operation makes sens=
e, that operation clearly should not transfer ownership.<br><br>Though I di=
d find something highly disconcerting. I see a lot of code taking `coroutin=
e_handle<>` by value. Since they take the parameter by value, that st=
rongly suggests <i>slicing</i> (copying of the base class). Maybe that'=
s OK, but I think it would be clearer if they took them by reference or som=
ething.<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><h2 style=3D"margin-top:1em;margin-bottom:16px;line-height:1.225;f=
ont-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-=
style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-f=
amily:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,=
sans-serif">resume/suspend</h2><p style=3D"margin-top:0px;margin-bottom:16p=
x;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'S=
egoe UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px">I=
think their purpose is different from=C2=A0<code style=3D"font-family:Cons=
olas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;pad=
ding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0=
392157)">await_transform</code>, they're desgined for RAII to complemen=
t unique-semantic in some cases.</p><h2 style=3D"margin-top:1em;margin-bott=
om:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bott=
om-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)=
;color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Se=
goe UI',Arial,freesans,sans-serif"><a href=3D"https://gist.github.com/j=
amboree/611b8c6551f853956f7d#initial_suspendfinal_suspend" style=3D"color:r=
gb(64,120,192);text-decoration:none;display:block;padding-right:6px;padding=
-left:30px;line-height:1;background-color:transparent" target=3D"_blank" re=
l=3D"nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url?q=
\75https%3A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23initia=
l_suspendfinal_suspend\46sa\75D\46sntz\0751\46usg\75AFQjCNE2vUN6R7vgRIJOx7B=
h61GWN_c-BQ';return true;" onclick=3D"this.href=3D'https://www.goog=
le.com/url?q\75https%3A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956=
f7d%23initial_suspendfinal_suspend\46sa\75D\46sntz\0751\46usg\75AFQjCNE2vUN=
6R7vgRIJOx7Bh61GWN_c-BQ';return true;"></a>initial_suspend/final_suspen=
d</h2><p style=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);fon=
t-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesa=
ns,sans-serif;font-size:16px;line-height:25.6px">I can't understand the=
rationale, I think the example of final_suspend you shown is exactly the s=
ame as the bool version, what's the difference?</p></div></div></blockq=
uote><div>P0054 explained exactly why the bool version doesn't work, wi=
th specific cases. It is complex, but the general gist is that there are ra=
ce conditions with threaded coroutine scheduling that make a `bool`-only ve=
rsion non-functional.<br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div><h2 style=3D"margin-top:1em;margin-bottom:16px;line-=
height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;=
border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51=
,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',A=
rial,freesans,sans-serif"></h2><h2 style=3D"margin-top:1em;margin-bottom:16=
px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-wi=
dth:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);colo=
r:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe U=
I',Arial,freesans,sans-serif"><a href=3D"https://gist.github.com/jambor=
ee/611b8c6551f853956f7d#auto-await-alternatives" style=3D"color:rgb(64,120,=
192);text-decoration:none;display:block;padding-right:6px;padding-left:30px=
;line-height:1;background-color:transparent" target=3D"_blank" rel=3D"nofol=
low" onmousedown=3D"this.href=3D'https://www.google.com/url?q\75https%3=
A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23auto-await-alter=
natives\46sa\75D\46sntz\0751\46usg\75AFQjCNFQiwrinswlgBuBHkxjyZM2TCrKaQ'=
;;return true;" onclick=3D"this.href=3D'https://www.google.com/url?q\75=
https%3A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23auto-awai=
t-alternatives\46sa\75D\46sntz\0751\46usg\75AFQjCNFQiwrinswlgBuBHkxjyZM2TCr=
KaQ';return true;"></a>auto await alternatives</h2><p style=3D"margin-t=
op:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Ne=
ue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16=
px;line-height:25.6px">Another benefit of resumable/async (whatever the mar=
k is called) approach is that you don't need to have=C2=A0<code style=
=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;=
font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-=
color:rgba(0,0,0,0.0392157)">await</code>=C2=A0and=C2=A0<code style=3D"font=
-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-siz=
e:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rg=
ba(0,0,0,0.0392157)">yield</code>=C2=A0as keywords, instead, they could be =
free functions=C2=A0<code style=3D"font-family:Consolas,'Liberation Mon=
o',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0p=
x;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">std::await</cod=
e>=C2=A0and<code style=3D"font-family:Consolas,'Liberation Mono',Me=
nlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-=
radius:3px;background-color:rgba(0,0,0,0.0392157)">std::<wbr>yield</code>. =
In the standard, you can define 2 pseudo keywords=C2=A0<code style=3D"font-=
family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size=
:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgb=
a(0,0,0,0.0392157)">__await</code>=C2=A0and=C2=A0<code style=3D"font-family=
:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6p=
x;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,=
0,0.0392157)">__yield</code>=C2=A0<wbr>and their semantic, the implementati=
on doesn't need to provide them, but the=C2=A0<code style=3D"font-famil=
y:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6=
px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0=
,0,0.0392157)">std::await</code>=C2=A0and=C2=A0<code style=3D"font-family:C=
onsolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;=
padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,=
0.0392157)">std::yield</code>=C2=A0<wbr>can be defined in terms of=C2=A0<co=
de style=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,mo=
nospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;bac=
kground-color:rgba(0,0,0,0.0392157)">__await</code>=C2=A0and=C2=A0<code sty=
le=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,monospac=
e;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;backgroun=
d-color:rgba(0,0,0,0.0392157)">__yield</code>=C2=A0<wbr>respectively:</p></=
div></div></blockquote><div>What are "pseudo keywords"? More impo=
rtantly, you can't make keywords (or any such semantic) with double-und=
erscores. That is explicitly reserved for <i>implementation</i> use, not st=
andard use.<br><br>Also, we shouldn't be judging a proposal to be bette=
r solely because it uses fewer keywords. We've got too many proposals i=
n the pipe that need genuine keywords to avoid adopting P0056 (soft keyword=
s). At which point, what is and isn't a keyword essentially becomes irr=
elevant.<br><br>If the committee rejects P0056, then an approach like the o=
ne you suggested could be adopted. But that really ought to be something th=
at gets dealt with once we're sure we have the functionality behaving c=
orrectly.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_401_461332557.1444485110310--
------=_Part_400_1763072859.1444485110309--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 07:22:23 -0700 (PDT)
Raw View
------=_Part_3835_1411186117.1444486943870
Content-Type: multipart/alternative;
boundary="----=_Part_3836_1592208030.1444486943870"
------=_Part_3836_1592208030.1444486943870
Content-Type: text/plain; charset=UTF-8
Hi Tongari:
First, I want to say that I find your contributions to await design highly
valuable and as you may have noticed, since N4402 you are on the
acknowledgment list. I did notice your act and CO2 libraries and consider
them to be a valuable source of design insights. So, thank you for doing
this work.
*RAII on coroutine handle:*
Consider task objects with RAII semantics. They attempt to destroy / cancel
the coroutine from their destructor. I consider that an owning use.
When await gives coroutine handle to an async operation it is an observer
use.
In NT, for example, a thing is controlled by two reference counts. One is
for the lifetime, this is usually a handle count, how many owners the
object has, that determines if there is an interest in the object. As soon
as the handle count goes to zero, the object is going to be deleted.
However, it cannot be deleted immediately, since there could be multiple
observers (async I/O in flight), cancel will be initiated and only when
observer count goes to zero.
Neither shared_ptr semantic, nor unique_ptr semantics can capture this
behavior. But let's consider something even simpler that has no async
involved. Let's take the generator example. Look at
<experimental/resumable> or the one shown in N4402.
There is one coroutine_handle in the generator object. Another is in the
iterator. Now let's make coroutine_handle<> to have RAII semantics a la
unique_ptr.
An iterator now has to store a pointer to a coroutine_handle<> as opposed
to just coroutine_handle. Now every ++ and deref operation has to do an
extra dereference to get the coroutine state.
By not having any smart semantics included in coroutine_handle<>, means it
does not impose any overhead. Higher level semantics can be done in a safe
manner in abstractions build on top of it.
I am a strong believer that a low-level API should focus on efficiency, not
user-friendliness. I observed may cases over the years when attempts to
make it easier to use low-level APIs resulted in inefficiencies that could
have been avoided if low-level just focused on efficiency and high-level
C++ wrappers focused on exposing safe high-level abstractions.
*initial_suspend/final_suspend*
Remember a few month back we had a discussion that suspend actually
consists of two parts. PrepareForSuspend and Suspend.
In await expansion, it looks like this:
if (!await_ready()) {
PrepareForSuspend();
await_suspend()
Suspend();
}
If initial_suspend returns bool where do I put PrepareForSuspend?
Option 1:
if (initial_suspend()) {
PrepareForSuspend();
Suspend();
}
That does not work, for explanation see P0054.
Okay, how do we fix it:
Option 2:
PrepareForSuspend();
if (initial_suspend()) {
Suspend();
}
Good. Race is fixed, but now we are inefficient. PrepareForSuspend() is now
done whether we need to suspend or not, so we need some way to ask
initial_suspend are your intending to suspend or not before, so that we can
bypass PrepareForSuspend. Voila, we just reinvented what await does.
*unwind*
If we make return_value awaitable, it will behave as:
await $p.return_value(expr);
If $p.return_value(expr) does a direct call to the consumer (say activating
the parent coroutine, there is no difference whether return_value is
awaitable or not).
However, consider the case, that coroutine is suspended and post resumption
of the parent on a threadpool. Then, the consumer will get the value
directly from the temporary on a coroutine frame. Without the ability for
return_value to request a suspend point the second case would not be
possible.
<https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>*auto
await alternatives*
At the moment I strongly believe that unobservable injection of suspend
points in the caller code will result in "expensive maintenance nightmare".
I showed how it can potentially be added in the future if need to.
The syntax proposed has been in use for a number of years in several
languages. It is loved by the users. And more and more languages are
getting the same syntax. Python (last May), EcmaScript 7, Dart sometime in
the last 12 month. I view it as an evidence that the syntax is sound.
--
---
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_3836_1592208030.1444486943870
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi Tongari:</div><div><br></div><div>
First, I want to say that=C2=A0I find your contributions to await design hi=
ghly valuable and as you may have noticed, since N4402 you are on the ackno=
wledgment list. I did notice your act and CO2 libraries and consider them t=
o be a valuable source of design insights. So, thank you for doing this wor=
k.</div><div><br></div><div><strong>RAII on coroutine handle:</strong></div=
><div><br></div><div>Consider task objects with RAII semantics. They attemp=
t to destroy / cancel the coroutine from their destructor. I consider that =
an owning use.</div><div>When await gives coroutine handle to an async oper=
ation it is an observer use. </div><div><br></div><div>In NT, for example, =
a thing is controlled by two reference counts. One is for the lifetime, thi=
s is usually a handle count, how many owners the object has, that determine=
s if there is an interest in the object. As soon as the handle count goes t=
o zero, the object is going to be deleted. However, it cannot be deleted im=
mediately, since there could be multiple observers (async I/O in flight), c=
ancel will be initiated and only when observer count goes to zero.</div><di=
v><br></div><div>Neither shared_ptr semantic, nor unique_ptr semantics can =
capture this behavior. But let's consider something even simpler that h=
as no async involved. Let's take the generator example. Look at <exp=
erimental/resumable> or the one shown in N4402.</div><div><br></div><div=
>There is one coroutine_handle in the generator object. Another is in the i=
terator. Now let's make coroutine_handle<> to have RAII semantics=
a la unique_ptr.</div><div>An iterator now has to store a pointer to a cor=
outine_handle<> as opposed to just coroutine_handle. Now every ++ and=
deref operation has to do an extra dereference to get the coroutine state.=
</div><div><div><br></div><div>By not having any smart semantics included i=
n coroutine_handle<>, means it does not impose any overhead. Higher l=
evel semantics can be done in a safe manner in abstractions build on top of=
it.</div><div><br></div><div>I am a strong believer that a low-level API s=
hould focus on efficiency, not user-friendliness. I observed may cases over=
the years when attempts to make it easier to use low-level APIs resulted i=
n inefficiencies that could have been avoided if low-level just focused on =
efficiency and high-level C++ wrappers focused on exposing safe high-level =
abstractions. </div><div><br></div></div><div><strong>initial_suspend/final=
_suspend</strong></div><div><br></div><div>Remember a few month back we had=
a discussion that suspend actually consists of two parts. PrepareForSuspen=
d and Suspend.</div><div>In await expansion, it looks like this:</div><div>=
<br></div><div>if (!await_ready()) {</div><div>=C2=A0=C2=A0 PrepareForSuspe=
nd();</div><div>=C2=A0=C2=A0 await_suspend()</div><div>=C2=A0=C2=A0 Suspend=
();</div><div>}</div><div><br></div><div>If initial_suspend returns bool wh=
ere do I put PrepareForSuspend?</div><div><br></div><div>Option 1:</div><di=
v><br></div><div>if (initial_suspend()) {</div><div><div>=C2=A0=C2=A0 Prepa=
reForSuspend();</div><div>=C2=A0=C2=A0 Suspend();</div>}</div><div><br></di=
v><div>That does not work, for explanation see P0054.</div><div>Okay, how d=
o we fix it:</div><div><br></div><div><div>Option 2:</div><div><br></div><d=
iv><div>PrepareForSuspend();</div>if (initial_suspend()) {</div><div><div>=
=C2=A0=C2=A0 Suspend();</div>}</div></div><div><br></div><div>Good. Race is=
fixed, but now we are inefficient. PrepareForSuspend() is now done whether=
we need to suspend or not, so we need some way to ask initial_suspend are =
your intending to suspend or not before, so that we can bypass PrepareForSu=
spend. Voila, we just reinvented what await does.</div><div><br></div><div>=
<strong>unwind</strong></div><div><br></div><div>If we make return_value aw=
aitable, it will behave as:</div><div><br></div><div>await $p.return_value(=
expr);</div><div><br></div><div>If $p.return_value(expr) does a direct call=
to the consumer (say activating the parent coroutine, there is no differen=
ce whether return_value is awaitable or not).</div><div>However, consider t=
he case, that coroutine is suspended and post resumption of the parent on a=
threadpool. Then, the consumer will get the value directly from the tempor=
ary on a coroutine frame. Without the ability for return_value to request a=
suspend point the second case would not be possible.</div><div><br></div><=
div><a style=3D"color: rgb(64, 120, 192); line-height: 1; padding-right: 6p=
x; padding-left: 30px; text-decoration: none; display: block; background-co=
lor: transparent;" onmousedown=3D"this.href=3D'https://www.google.com/u=
rl?q\75https%3A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23au=
to-await-alternatives\46sa\75D\46sntz\0751\46usg\75AFQjCNFQiwrinswlgBuBHkxj=
yZM2TCrKaQ';return true;" onclick=3D"this.href=3D'https://www.googl=
e.com/url?q\75https%3A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f=
7d%23auto-await-alternatives\46sa\75D\46sntz\0751\46usg\75AFQjCNFQiwrinswlg=
BuBHkxjyZM2TCrKaQ';return true;" href=3D"https://gist.github.com/jambor=
ee/611b8c6551f853956f7d#auto-await-alternatives" target=3D"_blank" rel=3D"n=
ofollow"></a><strong>auto await alternatives</strong></div><div><br></div><=
div>At the moment I strongly believe that unobservable injection of suspend=
points in the caller code will result in "expensive maintenance night=
mare". I showed how it can potentially be added in the future if need =
to.</div><div><br></div><div>The syntax proposed has been in use for a numb=
er of years in several languages. It is loved by the users. And more and mo=
re languages are getting the same syntax.=C2=A0 Python (last May), EcmaScri=
pt 7, Dart sometime in the last 12 month. I view it as an evidence that the=
syntax is sound.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3836_1592208030.1444486943870--
------=_Part_3835_1411186117.1444486943870--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 07:30:22 -0700 (PDT)
Raw View
------=_Part_3791_969879993.1444487423093
Content-Type: multipart/alternative;
boundary="----=_Part_3792_1828275727.1444487423094"
------=_Part_3792_1828275727.1444487423094
Content-Type: text/plain; charset=UTF-8
clarified incomplete sentence:
.... cancel will be initiated and only when observer count goes to zero
<added>*the object will be destroyed*.</added>
--
---
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_3792_1828275727.1444487423094
Content-Type: text/html; charset=UTF-8
<div dir="ltr"><div>clarified incomplete sentence:</div><div><br></div><div>... cancel will be initiated and only when observer count goes to zero <added><strong>the object will be destroyed</strong>.</added></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
------=_Part_3792_1828275727.1444487423094--
------=_Part_3791_969879993.1444487423093--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 07:43:53 -0700 (PDT)
Raw View
------=_Part_62_354260519.1444488233843
Content-Type: multipart/alternative;
boundary="----=_Part_63_1570228453.1444488233843"
------=_Part_63_1570228453.1444488233843
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, October 10, 2015 at 6:51:50 AM UTC-7, Nicol Bolas wrote:
>
> Though I did find something highly disconcerting. I see a lot of code=20
> taking `coroutine_handle<>` by value. Since they take the parameter by=20
> value, that strongly suggests *slicing* (copying of the base class).=20
> Maybe that's OK, but I think it would be clearer if they took them by=20
> reference or something.
>
By design coroutine_handle<> and coroutine<P> are pointer sized values.=20
coroutine_handle<> is a base class for coroutine_handle<P>. upcasting and=
=20
downcasting from one another does not change the bit pattern. It is still=
=20
the same pointer to the coroutine. coroutine_handle<P>, knows how given a=
=20
coroutine pointer to get access to the promise of the coroutine.=20
coroutine_handle<> only knows how to get to the coroutine.
Since it is a pointer sized value, it is cheaper to pass it by value and=20
not by reference.
I understand the perception you have and open to suggestions on how to=20
improve it. One thing to note that: P0057 has layered complexity (stealing=
=20
from N4287).
Everybody
=E2=80=A2 Safe by default, novice friendly: Use coroutines and awaitables d=
efined=20
by standard library and boost and other high quality libraries
=E2=80=A2 Power Users: Define new awaitables to customize await for their=
=20
environment using existing coroutine types
=E2=80=A2 Experts: Define new coroutine types
There will be significantly more users of coroutines of coroutines (let's=
=20
say 3,000,000 :-)) than those who define awaitables (1000?) and those who=
=20
define their own coroutine types (200?). We can educate the power users and=
=20
experts. They have very high pain resistance they do template=20
metaprogramming for breakfast :-).
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_63_1570228453.1444488233843
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, October 10, 2015 at 6:51:50 AM UTC-7, Nicol B=
olas wrote:<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>Though I did find something hi=
ghly disconcerting. I see a lot of code taking `coroutine_handle<>` b=
y value. Since they take the parameter by value, that strongly suggests <i>=
slicing</i> (copying of the base class). Maybe that's OK, but I think i=
t would be clearer if they took them by reference or something.</div></bloc=
kquote><div><br></div><div>By design coroutine_handle<> and coroutine=
<P> are pointer sized values. coroutine_handle<> is a base clas=
s for coroutine_handle<P>. upcasting and downcasting from one another=
does not change the bit pattern. It is still the same pointer to the corou=
tine. coroutine_handle<P>, knows how given a coroutine pointer to get=
access to the promise of the coroutine. coroutine_handle<> only know=
s how to get to the coroutine.</div><div><br></div><div>Since it is a point=
er sized value, it is cheaper to pass it by value and not by reference.</di=
v><div><br></div><div>I understand the perception you have and open to sugg=
estions on how to improve it. One thing to note that: P0057 has layered com=
plexity (stealing from N4287).</div><div><br></div><div>Everybody<br>=E2=80=
=A2 Safe by default, novice friendly: Use coroutines and awaitables defined=
by standard library and boost and other high quality libraries<br>=E2=80=
=A2 Power Users: Define new awaitables to customize await for their environ=
ment using existing coroutine types<br>=E2=80=A2 Experts: Define new corout=
ine types</div><div><br></div><div>There will be significantly more users o=
f coroutines of coroutines (let's say 3,000,000 :-)) than those who def=
ine awaitables (1000?) and those who define their own coroutine types (200?=
). We can educate the power users and experts. They have very high pain res=
istance they do template metaprogramming for breakfast :-).</div><div><br><=
/div><div><br></div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_63_1570228453.1444488233843--
------=_Part_62_354260519.1444488233843--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Sun, 11 Oct 2015 00:35:51 +0800
Raw View
--001a1140f9287873db0521c2b0a1
Content-Type: text/plain; charset=UTF-8
2015-10-10 21:51 GMT+08:00 Nicol Bolas <jmckesson@gmail.com>:
>
> On Saturday, October 10, 2015 at 4:08:56 AM UTC-4, TONGARI J wrote:
>>
>> The coro is taken by reference, so it can *transfer* the ownership of
>> the coroutine. If the coroutine is not transferred but is suspended, the
>> caller still owns the coroutine and can safely unwind the stack, it's
>> impossible without RAII at the first place.
>>
> This is a bit confusing, so I want to explain how I understand things.
>
> `await_suspend` is called by `await`. It is called on `e`, which is the
> evaluation of `operator await` on `await`'s expression. So the function
> call is `e.await_suspend`. It is given a coroutine handle that is the
> coroutine for *the current function*, not the coroutine that was just
> called. So `await_suspend` tells the promise object (converted by `operator
> await`) to suspend the current function.
>
The terminology here is a bit confusing, let me clarify that first:
* if the coroutine-return-type is `Future`,
`std::coroutine_traits<Future>::promise_type` is the coroutine-promise-type
* for `await expr`, the result of `operator await(expr)` is typically
called the "awaiter".
I assume what you mean by "promise object" is what we call "awaiter".
> Given all of that, if you were to transfer ownership of the current
> function's coroutine handle to the promise object, that would mean:
>
> 1) The current function actually *has ownership of itself* (you can't
> transfer ownership if you don't own something).
>
> 2) The coroutine promise from the `await`ing expression will own the
> current function now.
>
> #1 does not make sense. The owner of a coroutine is the *caller*, not the
> function itself (things can't own themselves uniquely). The caller has the
> right to destroy the coroutine when it is suspended, and there is no reason
> to deny the caller that right (for example, if the caller throws an
> exception).
>
> And I'm just not sure of the point of #2. Why do you want to give the
> coroutine promise that was just called ownership of the function that
> called it?
>
To explain it in English is quite tricky, let me try that in code:
```c++
std::coroutine<> fn()
{
await std::suspend_always{}; // [1]
await something_takes_the_ownership(); // [2]
}
....
std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
coro(); // caller - transfer the ownership at [2]
// now `coro` has no associated context
```
You can see that `coro` is the caller, and it's the coroutine that will be
transferred (i.e. what passed into `await_suspend`).
> Now P0057 is a complex proposal, so I may be misunderstanding what you and
> they are talking about. But from my limited comprehension of it, it seems
> like you're performing an action that doesn't make sense.
>
> Then again, I'm not sure why the `operator await` class from the promise
> being waited on is being told to suspend the function that called it. But
> to the extent that this operation makes sense, that operation clearly
> should not transfer ownership.
>
I'm not sure if "ownership" is the proper term, how about "the right to
execute the continuation"?
>
>> <https://gist.github.com/jamboree/611b8c6551f853956f7d#initial_suspendfinal_suspend>
>> initial_suspend/final_suspend
>>
>> I can't understand the rationale, I think the example of final_suspend
>> you shown is exactly the same as the bool version, what's the difference?
>>
> P0054 explained exactly why the bool version doesn't work, with specific
> cases. It is complex, but the general gist is that there are race
> conditions with threaded coroutine scheduling that make a `bool`-only
> version non-functional.
>
I don't see any code example for initial_suspend, so I'll skip that one for
now. My question was on the final_suspend example in that paper.
What is the difference between this:
```c++
auto final_suspend()
{
struct awaiter
{
promise_type * me;
bool await_ready() { return false; }
void await_resume() {}
bool await_suspend(coroutine_handle<>) {
auto need_suspending = (me->decrement_refcount() > 0);
return need_suspending;
}
};
return awaiter{this};
}
```
and this:
```c++
bool final_suspend()
{
auto need_suspending = (decrement_refcount() > 0);
return need_suspending;
}
```
? In my understanding, it only matters if `await_suspend` tends to execute
the continuation before it returns, but in the example, it's not the case,
I don't see why making the coroutine resumable matters before calling
`await_suspend` here.
>
>> <https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>auto
>> await alternatives
>>
>> Another benefit of resumable/async (whatever the mark is called) approach
>> is that you don't need to have await and yield as keywords, instead,
>> they could be free functions std::await andstd::yield. In the standard,
>> you can define 2 pseudo keywords __await and __yield and their semantic,
>> the implementation doesn't need to provide them, but the std::await and
>> std::yield can be defined in terms of __await and __yield respectively:
>>
> What are "pseudo keywords"? More importantly, you can't make keywords (or
> any such semantic) with double-underscores. That is explicitly reserved for
> *implementation* use, not standard use.
>
I mean they're only for definition purpose, they don't need to exist in
real.
--
---
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/.
--001a1140f9287873db0521c2b0a1
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-10 21:51 GMT+08:00 Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:=
jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>:<=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex"><span class=3D"">On Saturday, October 10, 2015 at 4:08:56 A=
M UTC-4, TONGARI J wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);=
border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><p style=3D"marg=
in-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue',Hel=
vetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;line-hei=
ght:25.6px;margin-top:0px!important"><span style=3D"line-height:25.6px">The=
=C2=A0</span><code style=3D"line-height:25.6px;font-family:Consolas,'Li=
beration Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0=
px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">cor=
o</code><span style=3D"line-height:25.6px">=C2=A0is taken by reference, so =
it can=C2=A0</span><i style=3D"line-height:25.6px">transfer</i><span style=
=3D"line-height:25.6px">=C2=A0the ownership of the coroutine. If the corout=
ine is not transferred but is suspended, the caller still owns the coroutin=
e and can safely unwind the stack, it's impossible without RAII at the =
first place.</span><br></p></div></blockquote></span><div>This is a bit con=
fusing, so I want to explain how I understand things.<br><br>`await_suspend=
` is called by `await`. It is called on `e`, which is the evaluation of `op=
erator await` on `await`'s expression. So the function call is `e.await=
_suspend`. It is given a coroutine handle that is the coroutine for <i>the =
current function</i>, not the coroutine that was just called. So `await_sus=
pend` tells the promise object (converted by `operator await`) to suspend t=
he current function.<br></div></blockquote><div><br></div><div>The terminol=
ogy here is a bit confusing, let me clarify that first:</div><div>* if the =
coroutine-return-type is `Future`, `std::coroutine_traits<Future>::pr=
omise_type` is the coroutine-promise-type</div><div>* for `await expr`, the=
result of `operator await(expr)` is typically called the "awaiter&quo=
t;.</div><div><br></div><div>I assume what you mean by "promise object=
" is what we call "awaiter".</div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-widt=
h:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-le=
ft:1ex"><div>Given all of that, if you were to transfer ownership of the cu=
rrent function's coroutine handle to the promise object, that would mea=
n:<br><br>1) The current function actually <i>has ownership of itself</i> (=
you can't transfer ownership if you don't own something).<br><br>2)=
The coroutine promise from the `await`ing expression will own the current =
function now.<br><br>#1 does not make sense. The owner of a coroutine is th=
e <i>caller</i>, not the function itself (things can't own themselves u=
niquely). The caller has the right to destroy the coroutine when it is susp=
ended, and there is no reason to deny the caller that right (for example, i=
f the caller throws an exception).<br><br>And I'm just not sure of the =
point of #2. Why do you want to give the coroutine promise that was just ca=
lled ownership of the function that called it?<br></div></blockquote><div><=
br></div><div>To explain it in English is quite tricky, let me try that in =
code:</div><div><br></div><div>```c++</div><div><div>std::coroutine<>=
fn()</div><div>{</div><div>=C2=A0 =C2=A0 await std::suspend_always{}; // [=
1]</div><div>=C2=A0 =C2=A0 await something_takes_the_ownership(); // [2]</d=
iv><div>}</div></div><div>...</div><div>std::coroutine<> coro =3D=C2=
=A0fn(); // stop at [1], `coro` owns the context</div><div>coro(); // calle=
r - transfer the ownership=C2=A0at [2]</div><div>// now `coro` has no assoc=
iated context</div><div>```</div><div><br></div><div>You can see that `coro=
` is the caller, and it's the coroutine that will be transferred (i.e. =
what passed into `await_suspend`).</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div>Now P0057 is a complex proposal, so I may be misunderstanding what you=
and they are talking about. But from my limited comprehension of it, it se=
ems like you're performing an action that doesn't make sense.<br><b=
r>Then again, I'm not sure why the `operator await` class from the prom=
ise being waited on is being told to suspend the function that called it. B=
ut to the extent that this operation makes sense, that operation clearly sh=
ould not transfer ownership.<br></div></blockquote><div><br></div><div>I=
9;m not sure if "ownership" is the proper term, how about "t=
he=C2=A0right to execute=C2=A0the continuation"?</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;b=
order-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"=
><span class=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex"><div dir=3D"ltr"><h2 style=3D"margin-top=
:1em;margin-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0=
..3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:=
rgb(238,238,238);color:rgb(51,51,51);font-family:'Helvetica Neue',H=
elvetica,'Segoe UI',Arial,freesans,sans-serif"><a href=3D"https://g=
ist.github.com/jamboree/611b8c6551f853956f7d#initial_suspendfinal_suspend" =
style=3D"color:rgb(64,120,192);text-decoration:none;display:block;padding-r=
ight:6px;padding-left:30px;line-height:1;background-color:transparent" rel=
=3D"nofollow" target=3D"_blank"></a>initial_suspend/final_suspend</h2><p st=
yle=3D"margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:&#=
39;Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-ser=
if;font-size:16px;line-height:25.6px">I can't understand the rationale,=
I think the example of final_suspend you shown is exactly the same as the =
bool version, what's the difference?</p></div></blockquote></span><div>=
P0054 explained exactly why the bool version doesn't work, with specifi=
c cases. It is complex, but the general gist is that there are race conditi=
ons with threaded coroutine scheduling that make a `bool`-only version non-=
functional.<br></div></blockquote><div><br></div>I don't see any code e=
xample for initial_suspend, so I'll skip that one for now. My question =
was on the final_suspend example in that paper.</div><div class=3D"gmail_qu=
ote"><br></div><div class=3D"gmail_quote">What is the difference between th=
is:</div><div class=3D"gmail_quote">```c++</div><div class=3D"gmail_quote">=
<div class=3D"gmail_quote">auto final_suspend()</div><div class=3D"gmail_qu=
ote">{</div><div class=3D"gmail_quote">=C2=A0 =C2=A0 struct awaiter</div><d=
iv class=3D"gmail_quote">=C2=A0 =C2=A0 {</div><div class=3D"gmail_quote">=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 promise_type * me;</div><div class=3D"gmail_quo=
te">=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool await_ready() { return false; }</div><=
div class=3D"gmail_quote">=C2=A0 =C2=A0 =C2=A0 =C2=A0 void await_resume() {=
}</div><div class=3D"gmail_quote">=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool await_su=
spend(coroutine_handle<>) {</div><div class=3D"gmail_quote">=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto need_suspending =3D (me->decreme=
nt_refcount() > 0);</div><div class=3D"gmail_quote">=C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 return need_suspending;</div><div class=3D"gmail_quot=
e">=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div class=3D"gmail_quote">=C2=A0 =C2=
=A0 };</div><div class=3D"gmail_quote">=C2=A0 =C2=A0 return awaiter{this};<=
/div><div class=3D"gmail_quote">}</div><div class=3D"gmail_quote">```</div>=
<div class=3D"gmail_quote">and this:</div><div class=3D"gmail_quote"><div c=
lass=3D"gmail_quote">```c++</div><div class=3D"gmail_quote"><div class=3D"g=
mail_quote">bool final_suspend()</div><div class=3D"gmail_quote">{</div><di=
v class=3D"gmail_quote">=C2=A0 =C2=A0 auto need_suspending =3D (decrement_r=
efcount() > 0);</div><div class=3D"gmail_quote">=C2=A0 =C2=A0 return nee=
d_suspending;</div><div class=3D"gmail_quote">}</div><div class=3D"gmail_qu=
ote">```</div><div class=3D"gmail_quote"><br></div><div class=3D"gmail_quot=
e">? In my understanding, it only matters if `await_suspend` tends to execu=
te the continuation before it returns, but in the example, it's not the=
case, I don't see why making the coroutine resumable matters before ca=
lling `await_suspend` here.</div></div></div></div><div class=3D"gmail_quot=
e"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:soli=
d;padding-left:1ex"><div></div><span class=3D""><blockquote class=3D"gmail_=
quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-=
color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=
=3D"ltr"><div><h2 style=3D"margin-top:1em;margin-bottom:16px;line-height:1.=
225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-bo=
ttom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);f=
ont-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,free=
sans,sans-serif"></h2><h2 style=3D"margin-top:1em;margin-bottom:16px;line-h=
eight:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;b=
order-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,=
51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Ar=
ial,freesans,sans-serif"><a href=3D"https://gist.github.com/jamboree/611b8c=
6551f853956f7d#auto-await-alternatives" style=3D"color:rgb(64,120,192);text=
-decoration:none;display:block;padding-right:6px;padding-left:30px;line-hei=
ght:1;background-color:transparent" rel=3D"nofollow" target=3D"_blank"></a>=
auto await alternatives</h2><p style=3D"margin-top:0px;margin-bottom:16px;c=
olor:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Sego=
e UI',Arial,freesans,sans-serif;font-size:16px;line-height:25.6px">Anot=
her benefit of resumable/async (whatever the mark is called) approach is th=
at you don't need to have=C2=A0<code style=3D"font-family:Consolas,'=
;Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2e=
m 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">=
await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Liberat=
ion Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;ma=
rgin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">yield</c=
ode>=C2=A0as keywords, instead, they could be free functions=C2=A0<code sty=
le=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,monospac=
e;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;backgroun=
d-color:rgba(0,0,0,0.0392157)">std::await</code>=C2=A0and<code style=3D"fon=
t-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-si=
ze:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:r=
gba(0,0,0,0.0392157)">std::yield</code>. In the standard, you can define 2 =
pseudo keywords=C2=A0<code style=3D"font-family:Consolas,'Liberation Mo=
no',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0=
px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">__await</code>=
=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono'=
;,Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;bor=
der-radius:3px;background-color:rgba(0,0,0,0.0392157)">__yield</code>=C2=A0=
and their semantic, the implementation doesn't need to provide them, bu=
t the=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono',Me=
nlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-=
radius:3px;background-color:rgba(0,0,0,0.0392157)">std::await</code>=C2=A0a=
nd=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono',Menlo=
,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-rad=
ius:3px;background-color:rgba(0,0,0,0.0392157)">std::yield</code>=C2=A0can =
be defined in terms of=C2=A0<code style=3D"font-family:Consolas,'Libera=
tion Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;m=
argin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">__await=
</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Liberation M=
ono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:=
0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">__yield</code=
>=C2=A0respectively:</p></div></div></blockquote></span><div>What are "=
;pseudo keywords"? More importantly, you can't make keywords (or a=
ny such semantic) with double-underscores. That is explicitly reserved for =
<i>implementation</i> use, not standard use.<br></div></blockquote><div><br=
></div><div>I mean they're only for definition purpose, they don't =
need to exist in real.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1140f9287873db0521c2b0a1--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 10 Oct 2015 11:14:27 -0700 (PDT)
Raw View
------=_Part_233_1504207750.1444500867848
Content-Type: multipart/alternative;
boundary="----=_Part_234_69336139.1444500867854"
------=_Part_234_69336139.1444500867854
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 12:35:52 PM UTC-4, TONGARI J wrote:
>
> 2015-10-10 21:51 GMT+08:00 Nicol Bolas <jmck...@gmail.com <javascript:>>:
>>
>> On Saturday, October 10, 2015 at 4:08:56 AM UTC-4, TONGARI J wrote:
>>>
>>> The coro is taken by reference, so it can *transfer* the ownership of
>>> the coroutine. If the coroutine is not transferred but is suspended, the
>>> caller still owns the coroutine and can safely unwind the stack, it's
>>> impossible without RAII at the first place.
>>>
>> This is a bit confusing, so I want to explain how I understand things.
>>
>> `await_suspend` is called by `await`. It is called on `e`, which is the
>> evaluation of `operator await` on `await`'s expression. So the function
>> call is `e.await_suspend`. It is given a coroutine handle that is the
>> coroutine for *the current function*, not the coroutine that was just
>> called. So `await_suspend` tells the promise object (converted by `operator
>> await`) to suspend the current function.
>>
>
> The terminology here is a bit confusing, let me clarify that first:
> * if the coroutine-return-type is `Future`,
> `std::coroutine_traits<Future>::promise_type` is the coroutine-promise-type
> * for `await expr`, the result of `operator await(expr)` is typically
> called the "awaiter".
>
> I assume what you mean by "promise object" is what we call "awaiter".
>
Yes. I got my terminology crossed up, but that's what I meant.
>
>
>> Given all of that, if you were to transfer ownership of the current
>> function's coroutine handle to the promise object, that would mean:
>>
>> 1) The current function actually *has ownership of itself* (you can't
>> transfer ownership if you don't own something).
>>
>> 2) The coroutine promise from the `await`ing expression will own the
>> current function now.
>>
>> #1 does not make sense. The owner of a coroutine is the *caller*, not
>> the function itself (things can't own themselves uniquely). The caller has
>> the right to destroy the coroutine when it is suspended, and there is no
>> reason to deny the caller that right (for example, if the caller throws an
>> exception).
>>
>> And I'm just not sure of the point of #2. Why do you want to give the
>> coroutine promise that was just called ownership of the function that
>> called it?
>>
>
> To explain it in English is quite tricky, let me try that in code:
>
> ```c++
> std::coroutine<> fn()
> {
> await std::suspend_always{}; // [1]
> await something_takes_the_ownership(); // [2]
> }
> ...
> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
> coro(); // caller - transfer the ownership at [2]
> // now `coro` has no associated context
> ```
>
> You can see that `coro` is the caller, and it's the coroutine that will be
> transferred (i.e. what passed into `await_suspend`).
>
I find this code to be rather dubious.
To whom is the ownership transferred? (with this being defined as you do:
"the right to execute the continuation", but we'll discuss that more later)
A thing cannot own itself; there would be no one available to continue it.
So the only thing this can do is transfer ownership to someone else.
Given that, why should the caller of the coroutine be ignorant of said
transference? That is, why shouldn't the code look like this:
std::coroutine<> fn()
{
await std::suspend_always{}; // [1]
}
....
std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
something_takes_the_ownership(std::move(coro));
//Now, coro is empty.
I think that makes a lot more sense. It makes it clear to the reader that
`coro` is no longer to be used. You can even encapsulate it in a factory
function, so that nobody can call `fn` directly.
This style of code also prevents this:
std::coroutine<> fn()
{
await std::suspend_always{}; // [1]
await something_takes_the_ownership(); // [2]
}
....
std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
coro(); // caller - transfer the ownership at [2]
// now `coro` has no associated context
coro(); //Well, it looked like a valid object...
By having your `std::coroutine` (which is a coroutine promise, and
therefore not the same thing as `coroutine_handle`) implement move
semantics, you make it clear that ownership of `coro` has been transferred
to someone else. It's not implicitly gone; it's explicitly gone.
If ownership means "right to call", and the caller of the coroutine had
that right, why should that right be lost without the caller *knowing*
about it? What you seem to want is conceptually no different from this:
unique_ptr<T> t = make_unique<T>(...);
t->TransferOwnership();
//t is now empty... somehow.
This doesn't work with smart pointers. And I don't know why you want it to
work with coroutines. Either way, it seems excessively dangerous.
Think of it like this. `coroutine_handle` is conceptually like a `T*`: it
is copyable and moveable, it has reference semantics, and it has absolutely
no ownership semantics. But like `T*`, you can build whatever ownership
semantics you need. If you want a coroutine promise type that has unique
ownership of the object, you can.
The only thing you can't do is the kind of automatic self-ownership that
`t->TransferOwnership()` would need in order to work.
> Now P0057 is a complex proposal, so I may be misunderstanding what you and
>> they are talking about. But from my limited comprehension of it, it seems
>> like you're performing an action that doesn't make sense.
>>
>> Then again, I'm not sure why the `operator await` class from the promise
>> being waited on is being told to suspend the function that called it. But
>> to the extent that this operation makes sense, that operation clearly
>> should not transfer ownership.
>>
>
> I'm not sure if "ownership" is the proper term, how about "the right to
> execute the continuation"?
>
I think "ownership" works well enough. If you have the right to continue
executing the coroutine, then you also have the right to destroy it. After
all, if you throw an exception, you need to clean yourself up. And
"yourself" now includes the coroutine.
But if you want to separate "person who destroys it" from "person who calls
it", you can do that too. You can implement a coroutine promise object that
has that distinction: someone can get the right to call it from the object,
which is transferrable. And someone can extract the right to destroy it.
It would basically be like a shared_ptr/weak_ptr relationship.
And this is easy to do precisely *because* `coroutine_promise` does not
implement ownership semantics. If it forced unique_coroutine-like
semantics, you'd have to do a lot of extra memory allocation or other
tricks to make it work.
>
>>> <https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>auto
>>> await alternatives
>>>
>>> Another benefit of resumable/async (whatever the mark is called)
>>> approach is that you don't need to have await and yield as keywords,
>>> instead, they could be free functions std::await andstd::yield. In the
>>> standard, you can define 2 pseudo keywords __await and __yield and
>>> their semantic, the implementation doesn't need to provide them, but the
>>> std::await and std::yield can be defined in terms of __await and __yield
>>> respectively:
>>>
>> What are "pseudo keywords"? More importantly, you can't make keywords (or
>> any such semantic) with double-underscores. That is explicitly reserved for
>> *implementation* use, not standard use.
>>
>
> I mean they're only for definition purpose, they don't need to exist in
> real.
>
Then why introduce them in the text at all? If you're going to have
`std::await` and `std::yield` as functions, then they should be standard
library functions with documentation as such. No need for "pseudo keywords"
"for definition purpose[s]". Just talk about what the functions do.
If you're going the resumable expressions route, do what P0114 does: make
it a function, period.
--
---
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_234_69336139.1444500867854
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, October 10, 2015 at 12:35:52 PM UTC-4, TONGARI J wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote">2015-10-10 21:51 GMT+08:00 Nicol Bolas <span dir=3D"ltr"><<a=
href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"YX34pVZlDQ=
AJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';retur=
n true;" onclick=3D"this.href=3D'javascript:';return true;">jmck...=
@gmail.com</a>></span>:<blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204)=
;border-left-style:solid;padding-left:1ex"><span>On Saturday, October 10, 2=
015 at 4:08:56 AM UTC-4, TONGARI J wrote:<blockquote class=3D"gmail_quote" =
style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:r=
gb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr">=
<p style=3D"margin-bottom:16px;color:rgb(51,51,51);font-family:'Helveti=
ca Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-si=
ze:16px;line-height:25.6px;margin-top:0px!important"><span style=3D"line-he=
ight:25.6px">The=C2=A0</span><code style=3D"line-height:25.6px;font-family:=
Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px=
;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0=
,0.0392157)">coro</code><span style=3D"line-height:25.6px">=C2=A0is taken b=
y reference, so it can=C2=A0</span><i style=3D"line-height:25.6px">transfer=
</i><span style=3D"line-height:25.6px">=C2=A0the ownership of the coroutine=
.. If the coroutine is not transferred but is suspended, the caller still ow=
ns the coroutine and can safely unwind the stack, it's impossible witho=
ut RAII at the first place.</span><br></p></div></blockquote></span><div>Th=
is is a bit confusing, so I want to explain how I understand things.<br><br=
>`await_suspend` is called by `await`. It is called on `e`, which is the ev=
aluation of `operator await` on `await`'s expression. So the function c=
all is `e.await_suspend`. It is given a coroutine handle that is the corout=
ine for <i>the current function</i>, not the coroutine that was just called=
.. So `await_suspend` tells the promise object (converted by `operator await=
`) to suspend the current function.<br></div></blockquote><div><br></div><d=
iv>The terminology here is a bit confusing, let me clarify that first:</div=
><div>* if the coroutine-return-type is `Future`, `std::coroutine_traits<=
;Future><wbr>::promise_type` is the coroutine-promise-type</div><div>* f=
or `await expr`, the result of `operator await(expr)` is typically called t=
he "awaiter".</div><div><br></div><div>I assume what you mean by =
"promise object" is what we call "awaiter".</div></div>=
</div></div></blockquote><div><br>Yes. I got my terminology crossed up, but=
that's what I meant.<br>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid=
;padding-left:1ex"><div>Given all of that, if you were to transfer ownershi=
p of the current function's coroutine handle to the promise object, tha=
t would mean:<br><br>1) The current function actually <i>has ownership of i=
tself</i> (you can't transfer ownership if you don't own something)=
..<br><br>2) The coroutine promise from the `await`ing expression will own t=
he current function now.<br><br>#1 does not make sense. The owner of a coro=
utine is the <i>caller</i>, not the function itself (things can't own t=
hemselves uniquely). The caller has the right to destroy the coroutine when=
it is suspended, and there is no reason to deny the caller that right (for=
example, if the caller throws an exception).<br><br>And I'm just not s=
ure of the point of #2. Why do you want to give the coroutine promise that =
was just called ownership of the function that called it?<br></div></blockq=
uote><div><br></div><div>To explain it in English is quite tricky, let me t=
ry that in code:</div><div><br></div><div>```c++</div><div><div>std::corout=
ine<> fn()</div><div>{</div><div>=C2=A0 =C2=A0 await std::suspend_alw=
ays{}; // [1]</div><div>=C2=A0 =C2=A0 await something_takes_the_ownership(<=
wbr>); // [2]</div><div>}</div></div><div>...</div><div>std::coroutine<&=
gt; coro =3D=C2=A0fn(); // stop at [1], `coro` owns the context</div><div>c=
oro(); // caller - transfer the ownership=C2=A0at [2]</div><div>// now `cor=
o` has no associated context</div><div>```</div><div><br></div><div>You can=
see that `coro` is the caller, and it's the coroutine that will be tra=
nsferred (i.e. what passed into `await_suspend`).</div></div></div></div></=
blockquote><div><br>I find this code to be rather dubious.<br><br>To whom i=
s the ownership transferred? (with this being defined as you do: "the=
=C2=A0right to execute=C2=A0the continuation", but we'll discuss t=
hat more later) A thing cannot own itself; there would be no one available =
to continue it. So the only thing this can do is transfer ownership to some=
one else.<br><br>Given that, why should the caller of the coroutine be igno=
rant of said transference? That is, why shouldn't the code look like th=
is:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">s=
td</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">coroutine</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify"><></span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> fn</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 await std</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">suspend_always</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">{};</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// [1]</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">.=
...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">coroutine</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify"><></span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> coro </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> fn</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"s=
tyled-by-prettify">// stop at [1], `coro` owns the context</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br><br>something_takes_the=
_ownership</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">move</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">coro</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">));</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br><br></span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//Now, coro is empty.</span></div></code></div><br>=
I think that makes a lot more sense. It makes it clear to the reader that `=
coro` is no longer to be used. You can even encapsulate it in a factory fun=
ction, so that nobody can call `fn` directly.<br><br>This style of code als=
o prevents this:<br><br><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">cor=
outine</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><=
></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> fn</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 await std</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">suspend_always</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">{};</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #800;" class=3D"styled-by-prettify">// [1]</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 await something_takes_t=
he_ownership</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #800;" class=3D"styled-by-prettify">// [2]</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>std</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">coroutine</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify"><></span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> coro </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> fn</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #800;" class=3D"styled-by-prettify">// stop at [1], `co=
ro` owns the context</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>coro</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// calle=
r - transfer the ownership at [2]</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">// now `coro` has no associated context</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>coro</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;=
" class=3D"styled-by-prettify">//Well, it looked like a valid object...</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></d=
iv></code></div><br>By having your `std::coroutine` (which is a coroutine p=
romise, and therefore not the same thing as `coroutine_handle`) implement m=
ove semantics, you make it clear that ownership of `coro` has been transfer=
red to someone else. It's not implicitly gone; it's explicitly gone=
..<br><br>If ownership means "right to call", and the caller of th=
e coroutine had that right, why should that right be lost without the calle=
r <i>knowing</i> about it? What you seem to want is conceptually no differe=
nt from this:<br><br><div class=3D"prettyprint" style=3D"background-color: =
rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; =
border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div=
class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">unique_ptr</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify"><</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> t </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> make_unique</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">>(...);</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>t</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">-></span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">TransferOwnership</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">//t is now empty... somehow.</span></div></code></d=
iv><br>This doesn't work with smart pointers. And I don't know why =
you want it to work with coroutines. Either way, it seems excessively dange=
rous.<br><br>Think of it like this. `coroutine_handle` is conceptually like=
a `T*`: it is copyable and moveable, it has reference semantics, and it ha=
s absolutely no ownership semantics. But like `T*`, you can build whatever =
ownership semantics you need. If you want a coroutine promise type that has=
unique ownership of the object, you can.<br><br>The only thing you can'=
;t do is the kind of automatic self-ownership that `t->TransferOwnership=
()` would need in order to work.<br>=C2=A0</div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div> </=
div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:sol=
id;padding-left:1ex"><div>Now P0057 is a complex proposal, so I may be misu=
nderstanding what you and they are talking about. But from my limited compr=
ehension of it, it seems like you're performing an action that doesn=
9;t make sense.<br><br>Then again, I'm not sure why the `operator await=
` class from the promise being waited on is being told to suspend the funct=
ion that called it. But to the extent that this operation makes sense, that=
operation clearly should not transfer ownership.<br></div></blockquote><di=
v><br></div><div>I'm not sure if "ownership" is the proper te=
rm, how about "the=C2=A0right to execute=C2=A0the continuation"?<=
/div></div></div></div></blockquote><div><br>I think "ownership" =
works well enough. If you have the right to continue executing the coroutin=
e, then you also have the right to destroy it. After all, if you throw an e=
xception, you need to clean yourself up. And "yourself" now inclu=
des the coroutine.<br><br>But if you want to separate "person who dest=
roys it" from "person who calls it", you can do that too. Yo=
u can implement a coroutine promise object that has that distinction: someo=
ne can get the right to call it from the object, which is transferrable. An=
d someone can extract the right to destroy it.<br><br>It would basically be=
like a shared_ptr/weak_ptr relationship.<br><br>And this is easy to do pre=
cisely <i>because</i> `coroutine_promise` does not implement ownership sema=
ntics. If it forced unique_coroutine-like semantics, you'd have to do a=
lot of extra memory allocation or other tricks to make it work.<br></div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div clas=
s=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex"><div></div><span><blockquote class=3D"gm=
ail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-l=
eft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div d=
ir=3D"ltr"><div><h2 style=3D"margin-top:1em;margin-bottom:16px;line-height:=
1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px;border-=
bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51)=
;font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,fr=
eesans,sans-serif"></h2><h2 style=3D"margin-top:1em;margin-bottom:16px;line=
-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom-width:1px=
;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(5=
1,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',=
Arial,freesans,sans-serif"><a href=3D"https://gist.github.com/jamboree/611b=
8c6551f853956f7d#auto-await-alternatives" style=3D"color:rgb(64,120,192);te=
xt-decoration:none;display:block;padding-right:6px;padding-left:30px;line-h=
eight:1;background-color:transparent" rel=3D"nofollow" target=3D"_blank" on=
mousedown=3D"this.href=3D'https://www.google.com/url?q\75https%3A%2F%2F=
gist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23auto-await-alternatives=
\46sa\75D\46sntz\0751\46usg\75AFQjCNFQiwrinswlgBuBHkxjyZM2TCrKaQ';retur=
n true;" onclick=3D"this.href=3D'https://www.google.com/url?q\75https%3=
A%2F%2Fgist.github.com%2Fjamboree%2F611b8c6551f853956f7d%23auto-await-alter=
natives\46sa\75D\46sntz\0751\46usg\75AFQjCNFQiwrinswlgBuBHkxjyZM2TCrKaQ'=
;;return true;"></a>auto await alternatives</h2><p style=3D"margin-top:0px;=
margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue'=
,Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;line=
-height:25.6px">Another benefit of resumable/async (whatever the mark is ca=
lled) approach is that you don't need to have=C2=A0<code style=3D"font-=
family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size=
:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgb=
a(0,0,0,0.0392157)">await</code>=C2=A0and=C2=A0<code style=3D"font-family:C=
onsolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;=
padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,=
0.0392157)">yield</code>=C2=A0as keywords, instead, they could be free func=
tions=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono',Me=
nlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-=
radius:3px;background-color:rgba(0,0,0,0.0392157)">std::await</code>=C2=A0a=
nd<code style=3D"font-family:Consolas,'Liberation Mono',Menlo,Couri=
er,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3p=
x;background-color:rgba(0,0,0,0.0392157)">std::<wbr>yield</code>. In the st=
andard, you can define 2 pseudo keywords=C2=A0<code style=3D"font-family:Co=
nsolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;p=
adding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0=
..0392157)">__await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas=
,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding=
:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.03921=
57)">__yield</code>=C2=A0<wbr>and their semantic, the implementation doesn&=
#39;t need to provide them, but the=C2=A0<code style=3D"font-family:Consola=
s,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;paddin=
g:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392=
157)">std::await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,&=
#39;Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0=
..2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157=
)">std::yield</code>=C2=A0<wbr>can be defined in terms of=C2=A0<code style=
=3D"font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;=
font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-=
color:rgba(0,0,0,0.0392157)">__await</code>=C2=A0and=C2=A0<code style=3D"fo=
nt-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-s=
ize:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:=
rgba(0,0,0,0.0392157)">__yield</code>=C2=A0<wbr>respectively:</p></div></di=
v></blockquote></span><div>What are "pseudo keywords"? More impor=
tantly, you can't make keywords (or any such semantic) with double-unde=
rscores. That is explicitly reserved for <i>implementation</i> use, not sta=
ndard use.<br></div></blockquote><div><br></div><div>I mean they're onl=
y for definition purpose, they don't need to exist in real.</div></div>=
</div></div></blockquote><div><br>Then why introduce them in the text at al=
l? If you're going to have `std::await` and `std::yield` as functions, =
then they should be standard library functions with documentation as such. =
No need for "pseudo keywords" "for definition purpose[s]&quo=
t;. Just talk about what the functions do.<br><br>If you're going the r=
esumable expressions route, do what P0114 does: make it a function, period.=
<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_234_69336139.1444500867854--
------=_Part_233_1504207750.1444500867848--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Sun, 11 Oct 2015 02:35:48 +0800
Raw View
--001a11409d8e6d2a770521c45db7
Content-Type: text/plain; charset=UTF-8
Hi Gor,
2015-10-10 22:22 GMT+08:00 Gor Nishanov <gornishanov@gmail.com>:
> Hi Tongari:
>
> First, I want to say that I find your contributions to await design highly
> valuable and as you may have noticed, since N4402 you are on the
> acknowledgment list. I did notice your act and CO2 libraries and consider
> them to be a valuable source of design insights. So, thank you for doing
> this work.
>
Yeah, I know I'll be a daily user of coroutine, so I just expressed the
concerns I have, with hope to have a better tool in future :)
> *RAII on coroutine handle:*
>
> Consider task objects with RAII semantics. They attempt to destroy /
> cancel the coroutine from their destructor. I consider that an owning use.
> When await gives coroutine handle to an async operation it is an observer
> use.
>
> In NT, for example, a thing is controlled by two reference counts. One is
> for the lifetime, this is usually a handle count, how many owners the
> object has, that determines if there is an interest in the object. As soon
> as the handle count goes to zero, the object is going to be deleted.
> However, it cannot be deleted immediately, since there could be multiple
> observers (async I/O in flight), cancel will be initiated and only when
> observer count goes to zero.
>
> Neither shared_ptr semantic, nor unique_ptr semantics can capture this
> behavior.
>
It sounds like exactly what shared_ptr does - a use-count & a weak-count.
Note that my proposed `coroutine` won't delete the coroutine-frame on
destruction, it only unwinds the stack (i.e. calling the local variables'
dtor), the entire coroutine-frame is still alive, meaning that the
observers can still access the frame(including the promise), they just
can't execute the coroutine anymore.
> But let's consider something even simpler that has no async involved.
> Let's take the generator example. Look at <experimental/resumable> or the
> one shown in N4402.
>
> There is one coroutine_handle in the generator object. Another is in the
> iterator. Now let's make coroutine_handle<> to have RAII semantics a la
> unique_ptr.
> An iterator now has to store a pointer to a coroutine_handle<> as opposed
> to just coroutine_handle. Now every ++ and deref operation has to do an
> extra dereference to get the coroutine state.
>
True, that's exactly how I do it in my implementation.
> By not having any smart semantics included in coroutine_handle<>, means it
> does not impose any overhead. Higher level semantics can be done in a safe
> manner in abstractions build on top of it.
>
> I am a strong believer that a low-level API should focus on efficiency,
> not user-friendliness. I observed may cases over the years when attempts to
> make it easier to use low-level APIs resulted in inefficiencies that could
> have been avoided if low-level just focused on efficiency and high-level
> C++ wrappers focused on exposing safe high-level abstractions.
>
I think it's important to get the semantic right. Indeed, the raw-semantic
is more efficient in some cases, but not always. In other cases if you want
to have the correct semantic, it tends to be harder and you'll end up with
a less efficient design.
> *initial_suspend/final_suspend*
>
> Remember a few month back we had a discussion that suspend actually
> consists of two parts. PrepareForSuspend and Suspend.
> In await expansion, it looks like this:
>
> if (!await_ready()) {
> PrepareForSuspend();
> await_suspend()
> Suspend();
> }
>
> If initial_suspend returns bool where do I put PrepareForSuspend?
>
> Option 1:
>
> if (initial_suspend()) {
> PrepareForSuspend();
> Suspend();
> }
>
> That does not work, for explanation see P0054.
> Okay, how do we fix it:
>
> Option 2:
>
> PrepareForSuspend();
> if (initial_suspend()) {
> Suspend();
> }
>
> Good. Race is fixed, but now we are inefficient. PrepareForSuspend() is
> now done whether we need to suspend or not, so we need some way to ask
> initial_suspend are your intending to suspend or not before, so that we can
> bypass PrepareForSuspend. Voila, we just reinvented what await does.
>
Admittedly I'm not sure about initial_suspend, but what's the difference in
the final_suspend example?
In my understanding, the order of `PrepareForSuspend` matters only if
`await_suspend` tends to execute the continuation before it returns, but in
the final_suspend example, it's not the case.
Note that I'm not against the idea to return Awaitable, I just don't
understand the final_suspend example you gave.
> *unwind*
>
> If we make return_value awaitable, it will behave as:
>
> await $p.return_value(expr);
>
> If $p.return_value(expr) does a direct call to the consumer (say
> activating the parent coroutine, there is no difference whether
> return_value is awaitable or not).
> However, consider the case, that coroutine is suspended and post
> resumption of the parent on a threadpool. Then, the consumer will get the
> value directly from the temporary on a coroutine frame. Without the ability
> for return_value to request a suspend point the second case would not be
> possible.
>
I'm not sure I understand, you now have to store the value in the
awaitable, what's the benefit?
<https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>*auto
> await alternatives*
>
> At the moment I strongly believe that unobservable injection of suspend
> points in the caller code will result in "expensive maintenance nightmare".
> I showed how it can potentially be added in the future if need to.
>
> The syntax proposed has been in use for a number of years in several
> languages. It is loved by the users. And more and more languages are
> getting the same syntax. Python (last May), EcmaScript 7, Dart sometime in
> the last 12 month. I view it as an evidence that the syntax is sound.
>
Not that I don't like the syntax, I just want to explore a way to 1) not
having await & yield as keywords. 2) make them as the building-blocks for
libraries, hiding them from direct usage.
--
---
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/.
--001a11409d8e6d2a770521c45db7
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Gor,<br><div class=3D"gmail_extra"><br><div class=3D"gm=
ail_quote">2015-10-10 22:22 GMT+08:00 Gor Nishanov <span dir=3D"ltr"><<a=
href=3D"mailto:gornishanov@gmail.com" target=3D"_blank">gornishanov@gmail.=
com</a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>Hi Tongari:</=
div><div><br></div><div>
First, I want to say that=C2=A0I find your contributions to await design hi=
ghly valuable and as you may have noticed, since N4402 you are on the ackno=
wledgment list. I did notice your act and CO2 libraries and consider them t=
o be a valuable source of design insights. So, thank you for doing this wor=
k.</div></div></blockquote><div><br></div><div>Yeah, I know I'll be a d=
aily user of coroutine, so I just expressed the concerns I have, with hope =
to have a better tool in future :)</div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;bo=
rder-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">=
<div dir=3D"ltr"><div></div><div><strong>RAII on coroutine handle:</strong>=
</div><div><br></div><div>Consider task objects with RAII semantics. They a=
ttempt to destroy / cancel the coroutine from their destructor. I consider =
that an owning use.</div><div>When await gives coroutine handle to an async=
operation it is an observer use. </div><div><br></div><div>In NT, for exam=
ple, a thing is controlled by two reference counts. One is for the lifetime=
, this is usually a handle count, how many owners the object has, that dete=
rmines if there is an interest in the object. As soon as the handle count g=
oes to zero, the object is going to be deleted. However, it cannot be delet=
ed immediately, since there could be multiple observers (async I/O in fligh=
t), cancel will be initiated and only when observer count goes to zero.</di=
v><div><br></div><div>Neither shared_ptr semantic, nor unique_ptr semantics=
can capture this behavior.</div></div></blockquote><div><br></div><div>It =
sounds like exactly what shared_ptr does - a use-count & a weak-count.<=
/div><div><br></div><div>Note that my proposed `coroutine` won't delete=
the=C2=A0coroutine-frame on destruction, it only unwinds the stack (i.e. c=
alling the local variables' dtor), the=C2=A0entire=C2=A0coroutine-frame=
is still alive, meaning that the observers can still access the frame(incl=
uding the promise), they just can't execute the coroutine anymore.</div=
><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>But let's cons=
ider something even simpler that has no async involved. Let's take the =
generator example. Look at <experimental/resumable> or the one shown =
in N4402.</div><div><br></div><div>There is one coroutine_handle in the gen=
erator object. Another is in the iterator. Now let's make coroutine_han=
dle<> to have RAII semantics a la unique_ptr.</div><div>An iterator n=
ow has to store a pointer to a coroutine_handle<> as opposed to just =
coroutine_handle. Now every ++ and deref operation has to do an extra deref=
erence to get the coroutine state.</div></div></blockquote><div><br></div><=
div>True, that's exactly how I do it in my implementation.</div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div><div></div><div>By not h=
aving any smart semantics included in coroutine_handle<>, means it do=
es not impose any overhead. Higher level semantics can be done in a safe ma=
nner in abstractions build on top of it.</div><div><br></div><div>I am a st=
rong believer that a low-level API should focus on efficiency, not user-fri=
endliness. I observed may cases over the years when attempts to make it eas=
ier to use low-level APIs resulted in inefficiencies that could have been a=
voided if low-level just focused on efficiency and high-level C++ wrappers =
focused on exposing safe high-level abstractions.</div></div></div></blockq=
uote><div><br></div><div>I think it's important to get the semantic rig=
ht. Indeed, the raw-semantic is more efficient in some cases, but not alway=
s. In other cases if you want to have the correct semantic, it tends to be =
harder and you'll end up with a less=C2=A0efficient design.</div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div><strong>initial_suspend/=
final_suspend</strong></div><div><br></div><div>Remember a few month back w=
e had a discussion that suspend actually consists of two parts. PrepareForS=
uspend and Suspend.</div><div>In await expansion, it looks like this:</div>=
<div><br></div><div>if (!await_ready()) {</div><div>=C2=A0=C2=A0 PrepareFor=
Suspend();</div><div>=C2=A0=C2=A0 await_suspend()</div><div>=C2=A0=C2=A0 Su=
spend();</div><div>}</div><div><br></div><div>If initial_suspend returns bo=
ol where do I put PrepareForSuspend?</div><div><br></div><div>Option 1:</di=
v><div><br></div><div>if (initial_suspend()) {</div><div><div>=C2=A0=C2=A0 =
PrepareForSuspend();</div><div>=C2=A0=C2=A0 Suspend();</div>}</div><div><br=
></div><div>That does not work, for explanation see P0054.</div><div>Okay, =
how do we fix it:</div><div><br></div><div><div>Option 2:</div><div><br></d=
iv><div><div>PrepareForSuspend();</div>if (initial_suspend()) {</div><div><=
div>=C2=A0=C2=A0 Suspend();</div>}</div></div><div><br></div><div>Good. Rac=
e is fixed, but now we are inefficient. PrepareForSuspend() is now done whe=
ther we need to suspend or not, so we need some way to ask initial_suspend =
are your intending to suspend or not before, so that we can bypass PrepareF=
orSuspend. Voila, we just reinvented what await does.</div></div></blockquo=
te><div><br></div><div>Admittedly I'm not sure about initial_suspend, b=
ut what's the difference in the final_suspend example?</div>In my under=
standing, the order of `PrepareForSuspend` matters only if `await_suspend` =
tends to execute the continuation before it returns, but in the=C2=A0final_=
suspend=C2=A0example, it's not the case.</div><div class=3D"gmail_quote=
"><br></div><div class=3D"gmail_quote">Note that I'm not against the id=
ea to return Awaitable, I just don't understand the=C2=A0final_suspend=
=C2=A0example you gave.</div><div class=3D"gmail_quote"><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex"><div dir=3D"ltr"><div></div><div><strong>unwind</strong></di=
v><div><br></div><div>If we make return_value awaitable, it will behave as:=
</div><div><br></div><div>await $p.return_value(expr);</div><div><br></div>=
<div>If $p.return_value(expr) does a direct call to the consumer (say activ=
ating the parent coroutine, there is no difference whether return_value is =
awaitable or not).</div><div>However, consider the case, that coroutine is =
suspended and post resumption of the parent on a threadpool. Then, the cons=
umer will get the value directly from the temporary on a coroutine frame. W=
ithout the ability for return_value to request a suspend point the second c=
ase would not be possible.</div></div></blockquote><div><br></div><div>I=
9;m not sure I understand, you now have to store the value in the awaitable=
, what's the benefit?</div><div><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"=
ltr"><div><a style=3D"color:rgb(64,120,192);line-height:1;padding-right:6px=
;padding-left:30px;text-decoration:none;display:block;background-color:tran=
sparent" href=3D"https://gist.github.com/jamboree/611b8c6551f853956f7d#auto=
-await-alternatives" rel=3D"nofollow" target=3D"_blank"></a><strong>auto aw=
ait alternatives</strong></div><div><br></div><div>At the moment I strongly=
believe that unobservable injection of suspend points in the caller code w=
ill result in "expensive maintenance nightmare". I showed how it =
can potentially be added in the future if need to.</div><div><br></div><div=
>The syntax proposed has been in use for a number of years in several langu=
ages. It is loved by the users. And more and more languages are getting the=
same syntax.=C2=A0 Python (last May), EcmaScript 7, Dart sometime in the l=
ast 12 month. I view it as an evidence that the syntax is sound.</div></div=
></blockquote><div><br></div><div>Not that I don't like the syntax, I j=
ust want to explore a way to 1) not having await & yield as keywords. 2=
) make them as the building-blocks for libraries, hiding them from direct u=
sage.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11409d8e6d2a770521c45db7--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Sun, 11 Oct 2015 03:39:45 +0800
Raw View
--e89a8f234afd27ce7a0521c542bd
Content-Type: text/plain; charset=UTF-8
2015-10-11 2:14 GMT+08:00 Nicol Bolas <jmckesson@gmail.com>:
> On Saturday, October 10, 2015 at 12:35:52 PM UTC-4, TONGARI J wrote:
>>
>> ```c++
>> std::coroutine<> fn()
>> {
>> await std::suspend_always{}; // [1]
>> await something_takes_the_ownership(); // [2]
>> }
>> ...
>> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
>> coro(); // caller - transfer the ownership at [2]
>> // now `coro` has no associated context
>> ```
>>
>> You can see that `coro` is the caller, and it's the coroutine that will
>> be transferred (i.e. what passed into `await_suspend`).
>>
>
> I find this code to be rather dubious.
>
> To whom is the ownership transferred?
>
Whoever wants to execute the continuation.
(with this being defined as you do: "the right to execute the
> continuation", but we'll discuss that more later) A thing cannot own
> itself; there would be no one available to continue it. So the only thing
> this can do is transfer ownership to someone else.
>
A `coroutine` owns the "execution-context", not itself, it can transfer the
context to others.
> Given that, why should the caller of the coroutine be ignorant of said
> transference? That is, why shouldn't the code look like this:
>
> std::coroutine<> fn()
> {
> await std::suspend_always{}; // [1]
> }
> ...
> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
>
> something_takes_the_ownership(std::move(coro));
>
> //Now, coro is empty.
>
> I think that makes a lot more sense. It makes it clear to the reader that
> `coro` is no longer to be used. You can even encapsulate it in a factory
> function, so that nobody can call `fn` directly.
>
Uh, that's just a demo how things work. In the "awaiter", what
`await_suspend` does is exactly `std::move(coro)`.
> This style of code also prevents this:
>
> std::coroutine<> fn()
> {
> await std::suspend_always{}; // [1]
> await something_takes_the_ownership(); // [2]
> }
> ...
> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
> coro(); // caller - transfer the ownership at [2]
> // now `coro` has no associated context
> coro(); //Well, it looked like a valid object...
>
> By having your `std::coroutine` (which is a coroutine promise, and
> therefore not the same thing as `coroutine_handle`) implement move
> semantics, you make it clear that ownership of `coro` has been transferred
> to someone else. It's not implicitly gone; it's explicitly gone.
>
It does implement move semantics, and no, it's not a coroutine promise,
it's a coroutine-return-type, but you're right that it's not the same as
`coroutine_handle` because the latter doesn't provide RAII semantic and
thus is not safe to be a coroutine-return-type.
> If ownership means "right to call", and the caller of the coroutine had
> that right, why should that right be lost without the caller *knowing*
> about it? What you seem to want is conceptually no different from this:
>
> unique_ptr<T> t = make_unique<T>(...);
> t->TransferOwnership();
> //t is now empty... somehow.
>
> This doesn't work with smart pointers. And I don't know why you want it to
> work with coroutines. Either way, it seems excessively dangerous.
>
It's more like this: `t->TransferOwnership(t);`
> Think of it like this. `coroutine_handle` is conceptually like a `T*`: it
> is copyable and moveable, it has reference semantics, and it has absolutely
> no ownership semantics. But like `T*`, you can build whatever ownership
> semantics you need. If you want a coroutine promise type that has unique
> ownership of the object, you can.
>
> The only thing you can't do is the kind of automatic self-ownership that
> `t->TransferOwnership()` would need in order to work.
>
It's not self-ownership but ownership-transfer.
> Now P0057 is a complex proposal, so I may be misunderstanding what you and
>>> they are talking about. But from my limited comprehension of it, it seems
>>> like you're performing an action that doesn't make sense.
>>>
>>> Then again, I'm not sure why the `operator await` class from the promise
>>> being waited on is being told to suspend the function that called it. But
>>> to the extent that this operation makes sense, that operation clearly
>>> should not transfer ownership.
>>>
>>
>> I'm not sure if "ownership" is the proper term, how about "the right to
>> execute the continuation"?
>>
>
> I think "ownership" works well enough. If you have the right to continue
> executing the coroutine, then you also have the right to destroy it. After
> all, if you throw an exception, you need to clean yourself up. And
> "yourself" now includes the coroutine.
>
It does have the right to destroy the coroutine-context.
> But if you want to separate "person who destroys it" from "person who
> calls it", you can do that too. You can implement a coroutine promise
> object that has that distinction: someone can get the right to call it from
> the object, which is transferrable. And someone can extract the right to
> destroy it.
>
> It would basically be like a shared_ptr/weak_ptr relationship.
>
> And this is easy to do precisely *because* `coroutine_promise` does not
> implement ownership semantics. If it forced unique_coroutine-like
> semantics, you'd have to do a lot of extra memory allocation or other
> tricks to make it work.
>
I have implemented
coroutine/generator/recursive_generator/task/shared_task/cancellable
task...etc and I didn't observe any extra memory allocation, as to tricks?
maybe.
>
>>>> <https://gist.github.com/jamboree/611b8c6551f853956f7d#auto-await-alternatives>auto
>>>> await alternatives
>>>>
>>>> Another benefit of resumable/async (whatever the mark is called)
>>>> approach is that you don't need to have await and yield as keywords,
>>>> instead, they could be free functions std::await andstd::yield. In the
>>>> standard, you can define 2 pseudo keywords __await and __yield and
>>>> their semantic, the implementation doesn't need to provide them, but the
>>>> std::await and std::yield can be defined in terms of __await and
>>>> __yield respectively:
>>>>
>>> What are "pseudo keywords"? More importantly, you can't make keywords
>>> (or any such semantic) with double-underscores. That is explicitly reserved
>>> for *implementation* use, not standard use.
>>>
>>
>> I mean they're only for definition purpose, they don't need to exist in
>> real.
>>
>
> Then why introduce them in the text at all? If you're going to have
> `std::await` and `std::yield` as functions, then they should be standard
> library functions with documentation as such. No need for "pseudo keywords"
> "for definition purpose[s]". Just talk about what the functions do.
>
> If you're going the resumable expressions route, do what P0114 does: make
> it a function, period.
>
Not the same as P0114, but they're not normal functions as well, the
implementation has to do some compiler magic (intrinsic). Anyway, that's
the matter of standard wording and out of the scope of this discussion.
--
---
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/.
--e89a8f234afd27ce7a0521c542bd
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-11 2:14 GMT+08:00 Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:j=
mckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;borde=
r-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid=
;padding-left:1ex">On Saturday, October 10, 2015 at 12:35:52 PM UTC-4, TONG=
ARI J wrote:<span class=3D""><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,2=
04);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div cl=
ass=3D"gmail_quote"><div>```c++</div><div><div>std::coroutine<> fn()<=
/div><div>{</div><div>=C2=A0 =C2=A0 await std::suspend_always{}; // [1]</di=
v><div>=C2=A0 =C2=A0 await something_takes_the_ownership(); // [2]</div><di=
v>}</div></div><div>...</div><div>std::coroutine<> coro =3D=C2=A0fn()=
; // stop at [1], `coro` owns the context</div><div>coro(); // caller - tra=
nsfer the ownership=C2=A0at [2]</div><div>// now `coro` has no associated c=
ontext</div><div>```</div><div><br></div><div>You can see that `coro` is th=
e caller, and it's the coroutine that will be transferred (i.e. what pa=
ssed into `await_suspend`).</div></div></div></div></blockquote></span><div=
><br>I find this code to be rather dubious.<br><br>To whom is the ownership=
transferred?</div></blockquote><div><br></div><div>Whoever wants to execut=
e the continuation.</div><div><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rg=
b(204,204,204);border-left-style:solid;padding-left:1ex"><div>(with this be=
ing defined as you do: "the=C2=A0right to execute=C2=A0the continuatio=
n", but we'll discuss that more later) A thing cannot own itself; =
there would be no one available to continue it. So the only thing this can =
do is transfer ownership to someone else.<br></div></blockquote><div><br></=
div><div>A `coroutine` owns the "execution-context", not itself, =
it can transfer the context to others.</div><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px=
;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1e=
x"><div>Given that, why should the caller of the coroutine be ignorant of s=
aid transference? That is, why shouldn't the code look like this:<br><b=
r><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;back=
ground-color:rgb(250,250,250)"><code><div><span class=3D""><span style=3D"c=
olor:rgb(0,0,0)">std</span><span style=3D"color:rgb(102,102,0)">::</span><s=
pan style=3D"color:rgb(0,0,0)">coroutine</span><span style=3D"color:rgb(102=
,102,0)"><></span><span style=3D"color:rgb(0,0,0)"> fn</span><span st=
yle=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br>=
</span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rg=
b(0,0,0)"><br>=C2=A0 =C2=A0 await std</span><span style=3D"color:rgb(102,10=
2,0)">::</span><span style=3D"color:rgb(0,0,0)">suspend_always</span><span =
style=3D"color:rgb(102,102,0)">{};</span><span style=3D"color:rgb(0,0,0)"> =
</span><span style=3D"color:rgb(136,0,0)">// [1]</span><span style=3D"color=
:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">}</span><span =
style=3D"color:rgb(0,0,0)"><br></span></span><span class=3D""><span style=
=3D"color:rgb(102,102,0)">...</span><span style=3D"color:rgb(0,0,0)"><br>st=
d</span><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"color:=
rgb(0,0,0)">coroutine</span><span style=3D"color:rgb(102,102,0)"><></=
span><span style=3D"color:rgb(0,0,0)"> coro </span><span style=3D"color:rgb=
(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> fn</span><span sty=
le=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"> </s=
pan><span style=3D"color:rgb(136,0,0)">// stop at [1], `coro` owns the cont=
ext</span></span><span style=3D"color:rgb(0,0,0)"><br><br>something_takes_t=
he_ownership</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,0,0)">std</span><span style=3D"color:rgb(102,102,0)">::</sp=
an><span style=3D"color:rgb(0,0,0)">move</span><span style=3D"color:rgb(102=
,102,0)">(</span><span style=3D"color:rgb(0,0,0)">coro</span><span style=3D=
"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br><br><=
/span><span style=3D"color:rgb(136,0,0)">//Now, coro is empty.</span></div>=
</code></div><br>I think that makes a lot more sense. It makes it clear to =
the reader that `coro` is no longer to be used. You can even encapsulate it=
in a factory function, so that nobody can call `fn` directly.<br></div></b=
lockquote><div><br></div><div>Uh, that's just a demo how things work. I=
n the "awaiter", what `await_suspend` does=C2=A0is exactly `std::=
move(coro)`.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div>This style of cod=
e also prevents this:<br><br><div style=3D"border:1px solid rgb(187,187,187=
);word-wrap:break-word;background-color:rgb(250,250,250)"><code><div><span =
class=3D""><span style=3D"color:rgb(0,0,0)">std</span><span style=3D"color:=
rgb(102,102,0)">::</span><span style=3D"color:rgb(0,0,0)">coroutine</span><=
span style=3D"color:rgb(102,102,0)"><></span><span style=3D"color:rgb=
(0,0,0)"> fn</span><span style=3D"color:rgb(102,102,0)">()</span><span styl=
e=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</s=
pan><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 await std</span><spa=
n style=3D"color:rgb(102,102,0)">::</span><span style=3D"color:rgb(0,0,0)">=
suspend_always</span><span style=3D"color:rgb(102,102,0)">{};</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">// [1]=
</span><span style=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 await something_t=
akes_the_ownership</span><span style=3D"color:rgb(102,102,0)">();</span><sp=
an style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">//=
[2]</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color=
:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br></span><span =
style=3D"color:rgb(102,102,0)">...</span><span style=3D"color:rgb(0,0,0)"><=
br>std</span><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"c=
olor:rgb(0,0,0)">coroutine</span><span style=3D"color:rgb(102,102,0)"><&=
gt;</span><span style=3D"color:rgb(0,0,0)"> coro </span><span style=3D"colo=
r:rgb(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> fn</span><spa=
n style=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"=
> </span><span style=3D"color:rgb(136,0,0)">// stop at [1], `coro` owns the=
context</span><span style=3D"color:rgb(0,0,0)"><br>coro</span><span style=
=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(136,0,0)">// caller - transfer the ownership at =
[2]</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:=
rgb(136,0,0)">// now `coro` has no associated context</span></span><span st=
yle=3D"color:rgb(0,0,0)"><br>coro</span><span style=3D"color:rgb(102,102,0)=
">();</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:r=
gb(136,0,0)">//Well, it looked like a valid object...</span><span style=3D"=
color:rgb(0,0,0)"><br></span></div></code></div><br>By having your `std::co=
routine` (which is a coroutine promise, and therefore not the same thing as=
`coroutine_handle`) implement move semantics, you make it clear that owner=
ship of `coro` has been transferred to someone else. It's not implicitl=
y gone; it's explicitly gone.<br></div></blockquote><div><br></div><div=
>It does implement move semantics, and no, it's not=C2=A0a coroutine pr=
omise, it's a coroutine-return-type, but you're right that it's=
not the same as `coroutine_handle` because the latter doesn't provide =
RAII semantic and thus is not safe to be a coroutine-return-type.</div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-=
style:solid;padding-left:1ex"><div>If ownership means "right to call&q=
uot;, and the caller of the coroutine had that right, why should that right=
be lost without the caller <i>knowing</i> about it? What you seem to want =
is conceptually no different from this:<br><br><div style=3D"border:1px sol=
id rgb(187,187,187);word-wrap:break-word;background-color:rgb(250,250,250)"=
><code><div><span style=3D"color:rgb(0,0,0)">unique_ptr</span><span style=
=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</sp=
an><span style=3D"color:rgb(102,102,0)">></span><span style=3D"color:rgb=
(0,0,0)"> t </span><span style=3D"color:rgb(102,102,0)">=3D</span><span sty=
le=3D"color:rgb(0,0,0)"> make_unique</span><span style=3D"color:rgb(102,102=
,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><span style=3D"col=
or:rgb(102,102,0)">>(...);</span><span style=3D"color:rgb(0,0,0)"><br>t<=
/span><span style=3D"color:rgb(102,102,0)">-></span><span style=3D"color=
:rgb(102,0,102)">TransferOwnership</span><span style=3D"color:rgb(102,102,0=
)">();</span><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"col=
or:rgb(136,0,0)">//t is now empty... somehow.</span></div></code></div><br>=
This doesn't work with smart pointers. And I don't know why you wan=
t it to work with coroutines. Either way, it seems excessively dangerous.<b=
r></div></blockquote><div><br></div><div>It's more like this: `t->Tr=
ansferOwnership(t);`</div><div>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color=
:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div>Think of i=
t like this. `coroutine_handle` is conceptually like a `T*`: it is copyable=
and moveable, it has reference semantics, and it has absolutely no ownersh=
ip semantics. But like `T*`, you can build whatever ownership semantics you=
need. If you want a coroutine promise type that has unique ownership of th=
e object, you can.<br><br>The only thing you can't do is the kind of au=
tomatic self-ownership that `t->TransferOwnership()` would need in order=
to work.<br></div></blockquote><div><br></div><div>It's not self-owner=
ship but ownership-transfer.</div><div>=C2=A0</div><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-le=
ft-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span c=
lass=3D""><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8=
ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-sty=
le:solid;padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote"=
><div> </div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-=
style:solid;padding-left:1ex"><div>Now P0057 is a complex proposal, so I ma=
y be misunderstanding what you and they are talking about. But from my limi=
ted comprehension of it, it seems like you're performing an action that=
doesn't make sense.<br><br>Then again, I'm not sure why the `opera=
tor await` class from the promise being waited on is being told to suspend =
the function that called it. But to the extent that this operation makes se=
nse, that operation clearly should not transfer ownership.<br></div></block=
quote><div><br></div><div>I'm not sure if "ownership" is the =
proper term, how about "the=C2=A0right to execute=C2=A0the continuatio=
n"?</div></div></div></div></blockquote></span><div><br>I think "=
ownership" works well enough. If you have the right to continue execut=
ing the coroutine, then you also have the right to destroy it. After all, i=
f you throw an exception, you need to clean yourself up. And "yourself=
" now includes the coroutine.<br></div></blockquote><div><br></div><di=
v>It does have the right to destroy=C2=A0the coroutine-context.</div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div>But if you want to separate "person =
who destroys it" from "person who calls it", you can do that=
too. You can implement a coroutine promise object that has that distinctio=
n: someone can get the right to call it from the object, which is transferr=
able. And someone can extract the right to destroy it.<br><br>It would basi=
cally be like a shared_ptr/weak_ptr relationship.<br><br>And this is easy t=
o do precisely <i>because</i> `coroutine_promise` does not implement owners=
hip semantics. If it forced unique_coroutine-like semantics, you'd have=
to do a lot of extra memory allocation or other tricks to make it work.<br=
></div></blockquote><div><br></div><div>I have implemented coroutine/genera=
tor/recursive_generator/task/shared_task/cancellable task...etc and I didn&=
#39;t observe any=C2=A0extra memory allocation, as to tricks? maybe.</div><=
blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l=
eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa=
dding-left:1ex"><div></div><span class=3D""><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div></div><span><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-=
width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div><h2 style=3D"margin-top:1em;margin-bottom=
:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;border-bottom=
-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);c=
olor:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Sego=
e UI',Arial,freesans,sans-serif"></h2><h2 style=3D"margin-top:1em;margi=
n-bottom:16px;line-height:1.225;font-size:1.75em;padding-bottom:0.3em;borde=
r-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,23=
8,238);color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,&=
#39;Segoe UI',Arial,freesans,sans-serif"><a href=3D"https://gist.github=
..com/jamboree/611b8c6551f853956f7d#auto-await-alternatives" style=3D"color:=
rgb(64,120,192);text-decoration:none;display:block;padding-right:6px;paddin=
g-left:30px;line-height:1;background-color:transparent" rel=3D"nofollow" ta=
rget=3D"_blank"></a>auto await alternatives</h2><p style=3D"margin-top:0px;=
margin-bottom:16px;color:rgb(51,51,51);font-family:'Helvetica Neue'=
,Helvetica,'Segoe UI',Arial,freesans,sans-serif;font-size:16px;line=
-height:25.6px">Another benefit of resumable/async (whatever the mark is ca=
lled) approach is that you don't need to have=C2=A0<code style=3D"font-=
family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size=
:13.6px;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgb=
a(0,0,0,0.0392157)">await</code>=C2=A0and=C2=A0<code style=3D"font-family:C=
onsolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;=
padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,=
0.0392157)">yield</code>=C2=A0as keywords, instead, they could be free func=
tions=C2=A0<code style=3D"font-family:Consolas,'Liberation Mono',Me=
nlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-=
radius:3px;background-color:rgba(0,0,0,0.0392157)">std::await</code>=C2=A0a=
nd<code style=3D"font-family:Consolas,'Liberation Mono',Menlo,Couri=
er,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;border-radius:3p=
x;background-color:rgba(0,0,0,0.0392157)">std::yield</code>. In the standar=
d, you can define 2 pseudo keywords=C2=A0<code style=3D"font-family:Consola=
s,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;paddin=
g:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392=
157)">__await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'=
;Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2e=
m 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">=
__yield</code>=C2=A0and their semantic, the implementation doesn't need=
to provide them, but the=C2=A0<code style=3D"font-family:Consolas,'Lib=
eration Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0p=
x;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">std:=
:await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consolas,'Libera=
tion Mono',Menlo,Courier,monospace;font-size:13.6px;padding:0.2em 0px;m=
argin:0px;border-radius:3px;background-color:rgba(0,0,0,0.0392157)">std::yi=
eld</code>=C2=A0can be defined in terms of=C2=A0<code style=3D"font-family:=
Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px=
;padding:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0=
,0.0392157)">__await</code>=C2=A0and=C2=A0<code style=3D"font-family:Consol=
as,'Liberation Mono',Menlo,Courier,monospace;font-size:13.6px;paddi=
ng:0.2em 0px;margin:0px;border-radius:3px;background-color:rgba(0,0,0,0.039=
2157)">__yield</code>=C2=A0respectively:</p></div></div></blockquote></span=
><div>What are "pseudo keywords"? More importantly, you can't=
make keywords (or any such semantic) with double-underscores. That is expl=
icitly reserved for <i>implementation</i> use, not standard use.<br></div><=
/blockquote><div><br></div><div>I mean they're only for definition purp=
ose, they don't need to exist in real.</div></div></div></div></blockqu=
ote></span><div><br>Then why introduce them in the text at all? If you'=
re going to have `std::await` and `std::yield` as functions, then they shou=
ld be standard library functions with documentation as such. No need for &q=
uot;pseudo keywords" "for definition purpose[s]". Just talk =
about what the functions do.<br><br>If you're going the resumable expre=
ssions route, do what P0114 does: make it a function, period.<br></div></bl=
ockquote><div><br></div><div>Not the same as P0114, but they're not nor=
mal functions as well, the implementation has to do some compiler magic (in=
trinsic). Anyway, that's the matter of standard wording and out of the =
scope of this discussion.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--e89a8f234afd27ce7a0521c542bd--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 13:37:01 -0700 (PDT)
Raw View
------=_Part_4053_1312910974.1444509421225
Content-Type: multipart/alternative;
boundary="----=_Part_4054_201825308.1444509421225"
------=_Part_4054_201825308.1444509421225
Content-Type: text/plain; charset=UTF-8
Hi Tongari:
Low level APIs need to worry about efficiency, high level APIs need to
worry about beauty of abstraction and safety while using low level APIs to
do it efficiently.
It is possible to give coroutine_handle a unique_ptr like semantic, but,
now we pessimized performance in at least three areas:
1) mandatory extra dereference in coroutine observers
2) ownership transfer. Now there is always a = nullptr whenever I move it
around
3) now there must be a mandatory branch in the destructor if (_Ptr)
coro.destroy()
Moreover, we gave the higher-level semantics to the coroutine_handle. If
that does not match what the library wants to do, it now needs to add code
to suppress that behavior, (for example if it does not want ownership
semantic, it should zero out the handle before the destruction).
coroutine_handle is not for the end user. It is a sharp tool for the
library writer. Moreover it is a compiler provided tool. If I don't like
the library, I can write my own. If I don't like what compiler gives me, I
am not going to write a new compiler.
Currently, it is a raw pointer. You cannot get any more efficient than
that. It is fully devoid of higher level semantics. As a library writer you
decide what it means. You decide what trade-offs to do and what efficiency
you want to sacrifice for ease of use. I as a compiler don't want to make
any trade-offs. I give pretty syntactic sugar to the end-user and a bunch
of sharp knives to the library developer.
I am open to any suggestions how to make the library adaptation layers more
library writer friendly as long as I don't have to sacrifice performance in
space or time.
*On keywords:*
It is not about keywords, correct? P0071 offers a magic std::await and
std::yield functions as an alternative.
Your concern is with design point that P0054 requires that every suspend
point in a function needs to be explicitly marked whether with a keyword or
magic function.
I have no objections to exploring whether in the future we may get
"automatically awaited awaitables" or async functions as you suggested in
your proposal on the github. Sure thing. Go right ahead. Should we wait and
not standardize coroutines while this exploration is going on?
There reason I added the section about it in P0054 was to show that such
exploration is possible in the future. It should not stop progress on this
proposal.
*On awaitable return_value*
I store a reference to the expression (lvalue or temporary on the coroutine
frame) and give a chance to consumer, potentially running on a different
thread to observe it before semicolon at the end of full expression
destroys the value (or leaving the scope and stopping at final suspend
destroys the lvalue that I was trying to return)
*On final_suspend*
I am afraid I cannot answer that without pasting here what I've written in
P0054. If one of the steps described in P0054 is unclear. Ask me, why Y
follows from X. Otherwise, I am not sure how I can help.
--
---
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_4054_201825308.1444509421225
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi Tongari:</div><div><br></div><div>Low level APIs n=
eed to worry about efficiency, high level APIs need to worry about beauty o=
f abstraction and safety while using low level APIs to do it efficiently.</=
div><div>It is possible to give coroutine_handle a unique_ptr like semantic=
, but, now we pessimized performance in at least three areas:</div><div><br=
></div><div>1) mandatory extra dereference in coroutine observers</div><div=
>2) ownership transfer. Now there is always a =3D nullptr whenever I move i=
t around</div><div>3) now there must be a mandatory branch in the destructo=
r if (_Ptr) coro.destroy()</div><div><br></div><div>Moreover, we gave the h=
igher-level semantics to the coroutine_handle. If that does not match what =
the library wants to do,=C2=A0it=C2=A0now needs to add code to suppress tha=
t behavior, (for example if=C2=A0it does not want ownership semantic,=C2=A0=
it should zero out the handle before the destruction).</div><div><br></div>=
<div>coroutine_handle is not for the end user. It is a sharp tool for the l=
ibrary writer. Moreover it is a compiler provided tool. If I don't like=
the library, I can write my own. If I don't like what compiler gives m=
e, I am not going to write a new compiler.</div><div><br></div><div>Current=
ly, it is a raw pointer. You cannot get any more efficient than that. It is=
fully devoid of higher level semantics. As a library writer you decide wha=
t it means. You decide what trade-offs to do and what efficiency you want t=
o sacrifice for ease of use. I as a compiler don't want to make any tra=
de-offs. I give pretty syntactic sugar to the end-user and=C2=A0a bunch of =
sharp knives to the library developer.</div><div><br></div><div>I am open t=
o any suggestions how to make the library adaptation layers more library wr=
iter friendly as long as I don't have to sacrifice performance in space=
or time.</div><div><br></div><div><strong>On keywords:</strong></div><div>=
<br></div><div>It is not about keywords, correct? P0071 offers a magic std:=
:await and std::yield functions as an alternative.</div><div>Your concern i=
s with design point that P0054 requires that every suspend point in=C2=A0a =
function needs to be explicitly marked whether with a keyword or magic func=
tion. </div><div><br></div><div>I have no objections=C2=A0to exploring whet=
her in the future we may get "automatically awaited awaitables" o=
r async functions as you suggested in your proposal on the github. Sure thi=
ng. Go right ahead. Should we wait and not standardize coroutines while thi=
s exploration is going on?<br><br>There reason=C2=A0I added the section abo=
ut it in P0054 was to show that such exploration is possible in the future.=
It should not stop progress on this proposal.</div><div><br></div><div><st=
rong>On awaitable return_value</strong></div><div><br></div><div>I store=C2=
=A0a reference to the expression (lvalue or temporary on the coroutine fram=
e) and give a chance to consumer, potentially running on a different thread=
to observe it before semicolon at the end of full expression destroys the =
value (or leaving the scope and stopping at final suspend destroys the lval=
ue that I was trying to return)</div><div><br></div><div><strong>On final_s=
uspend</strong></div><div><br></div><div>I am afraid I cannot answer that w=
ithout pasting here what I've written in P0054. If one of the steps des=
cribed in P0054 is unclear. Ask me, why Y follows from X. Otherwise, I am n=
ot sure how I can help.</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4054_201825308.1444509421225--
------=_Part_4053_1312910974.1444509421225--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 13:46:46 -0700 (PDT)
Raw View
------=_Part_4155_1861883371.1444510006204
Content-Type: multipart/alternative;
boundary="----=_Part_4156_1310771279.1444510006204"
------=_Part_4156_1310771279.1444510006204
Content-Type: text/plain; charset=UTF-8
Missed one question.
On Saturday, October 10, 2015 at 11:35:50 AM UTC-7, TONGARI J wrote:
>
> In NT, for example, a thing is controlled by two reference counts. One is
>> for the lifetime, this is usually a handle count, how many owners the
>> object has, that determines if there is an interest in the object. As soon
>> as the handle count goes to zero, the object is going to be deleted.
>> However, it cannot be deleted immediately, since there could be multiple
>> observers (async I/O in flight), cancel will be initiated and only when
>> observer count goes to zero.
>>
>> Neither shared_ptr semantic, nor unique_ptr semantics can capture this
>> behavior.
>>
>
> It sounds like exactly what shared_ptr does - a use-count & a weak-count.
>
It may sound similar, but, it is not. Usage protocol is different. With
shared_ptr/weak_ptr, there is an agreement that I am not going to touch
your memory before I successfully lock the weak_ptr. Network card, on the
other hand, is not going lock weak_ptr before blasting the memory with data.
If there is an outstanding observer that can touch the memory of the
object, I cannot let the memory go away. The observer could be a different
machine using RDMA to access the memory of my object, for example.
--
---
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_4156_1310771279.1444510006204
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Missed one question.<br><br>On Saturday, October 10, 2015 =
at 11:35:50 AM UTC-7, TONGARI J wrote:<blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(=
204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" =
style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: r=
gb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div =
dir=3D"ltr"><div>In NT, for example, a thing is controlled by two reference=
counts. One is for the lifetime, this is usually a handle count, how many =
owners the object has, that determines if there is an interest in the objec=
t. As soon as the handle count goes to zero, the object is going to be dele=
ted. However, it cannot be deleted immediately, since there could be multip=
le observers (async I/O in flight), cancel will be initiated and only when =
observer count goes to zero.</div><div><br></div><div>Neither shared_ptr se=
mantic, nor unique_ptr semantics can capture this behavior.</div></div></bl=
ockquote><div><br></div><div>It sounds like exactly what shared_ptr does - =
a use-count & a weak-count.<br></div></div></div></div></blockquote><di=
v><br></div><div>It may sound similar, but, it is not. Usage protocol is di=
fferent. With shared_ptr/weak_ptr, there is an agreement that I am not goin=
g to touch your memory before I successfully lock the weak_ptr. Network car=
d, on the other hand,=C2=A0is not going lock weak_ptr=C2=A0before blasting =
the memory with data.</div><div><br></div><div>If there is an outstanding o=
bserver that can touch the memory of the object, I cannot let the memory go=
away. The observer could be a different machine using RDMA to access the m=
emory of my object, for example.</div><div><br></div>
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4156_1310771279.1444510006204--
------=_Part_4155_1861883371.1444510006204--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 10 Oct 2015 15:03:04 -0700 (PDT)
Raw View
------=_Part_3123_1164530807.1444514584166
Content-Type: multipart/alternative;
boundary="----=_Part_3124_1379333446.1444514584167"
------=_Part_3124_1379333446.1444514584167
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 3:39:47 PM UTC-4, TONGARI J wrote:
>
> 2015-10-11 2:14 GMT+08:00 Nicol Bolas <jmck...@gmail.com <javascript:>>:
>
>> On Saturday, October 10, 2015 at 12:35:52 PM UTC-4, TONGARI J wrote:
>>>
>>> ```c++
>>> std::coroutine<> fn()
>>> {
>>> await std::suspend_always{}; // [1]
>>> await something_takes_the_ownership(); // [2]
>>> }
>>> ...
>>> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
>>> coro(); // caller - transfer the ownership at [2]
>>> // now `coro` has no associated context
>>> ```
>>>
>>> You can see that `coro` is the caller, and it's the coroutine that will
>>> be transferred (i.e. what passed into `await_suspend`).
>>>
>>
>> I find this code to be rather dubious.
>>
>> To whom is the ownership transferred?
>>
>
> Whoever wants to execute the continuation.
>
> (with this being defined as you do: "the right to execute the
>> continuation", but we'll discuss that more later) A thing cannot own
>> itself; there would be no one available to continue it. So the only thing
>> this can do is transfer ownership to someone else.
>>
>
> A `coroutine` owns the "execution-context", not itself, it can transfer
> the context to others.
>
I don't know what you mean by "execution context".
If you mean "all of the information needed to be able to resume execution",
we have a word for that: "coroutine". It's a function, a piece of memory
representing its stack variables, and whatever other bits of information
are needed to That's all a coroutine is: what is needed to resume execution
after execution is paused. So if that's what you mean by "execution
context", then we seem to be in agreement.
If you mean something else, well, I'm not sure what that would be.
>
> Given that, why should the caller of the coroutine be ignorant of said
>> transference? That is, why shouldn't the code look like this:
>>
>> std::coroutine<> fn()
>> {
>> await std::suspend_always{}; // [1]
>> }
>> ...
>> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
>>
>> something_takes_the_ownership(std::move(coro));
>>
>> //Now, coro is empty.
>>
>> I think that makes a lot more sense. It makes it clear to the reader that
>> `coro` is no longer to be used. You can even encapsulate it in a factory
>> function, so that nobody can call `fn` directly.
>>
>
> Uh, that's just a demo how things work. In the "awaiter", what
> `await_suspend` does is exactly `std::move(coro)`.
>
I'm aware of that. I understand that, somewhere in some library code,
movement took place. `std::move` was called.
My point is that this is *not apparent to the user*. They don't know it
happened without looking it up in documentation.
In normal code, if you want to move something, the person who currently own
it must agree to the move, typically by using `std::move`. If you have a
sequence of functions that all take `unique_ptr`, each and every one of
them must std::move their value into each function call. Thus making it
clear that ownership is being transferred at each call site.
We agree that the function who called the coroutine owns it immediately
after this call. And you want the function who owns the coroutine to lose
ownership of it, simply by having resumed it.
That is not a transferal of ownership. In a transfer of ownership, the
source and destination both agree that the source is losing ownership and
the destination is gaining it.
What you want to do is not *give* ownership; you want to *steal* it. You
had the coroutine arbitrarily decide that the caller no longer has the
right to call it. This code cannot be statically inspected to know that
this has happened, not without the coroutine function's implementation.
I would consider this to be *perfidy*; code willfully lying to other code.
This is also why I consider it a code smell to move from a parameter that
is not a value or an rvalue reference. Either the function moves from it or
it doesn't; it shouldn't "sometimes maybe kinda could do so". How can you
possibly write safe code if you don't even know whether the object will be
valid after calling it?
I'm sure you've implemented a coroutine system that does this. That doesn't
make it a good idea.
This style of code also prevents this:
>>
>> std::coroutine<> fn()
>> {
>> await std::suspend_always{}; // [1]
>> await something_takes_the_ownership(); // [2]
>> }
>> ...
>> std::coroutine<> coro = fn(); // stop at [1], `coro` owns the context
>> coro(); // caller - transfer the ownership at [2]
>> // now `coro` has no associated context
>> coro(); //Well, it looked like a valid object...
>>
>> By having your `std::coroutine` (which is a coroutine promise, and
>> therefore not the same thing as `coroutine_handle`) implement move
>> semantics, you make it clear that ownership of `coro` has been transferred
>> to someone else. It's not implicitly gone; it's explicitly gone.
>>
>
> It does implement move semantics, and no, it's not a coroutine promise,
> it's a coroutine-return-type,
>
By P0057, the return type of a coroutine *must* be a coroutine promise, as
defined in 18.11.4. That is what the "coroutine-return-type" is called.
> but you're right that it's not the same as `coroutine_handle` because the
> latter doesn't provide RAII semantic and thus is not safe to be a
> coroutine-return-type.
>
That is *not* why coroutines don't directly return a `coroutine_handle`.
The point of the distinction between coroutine promises and coroutine
handles is to allow users to build higher-level semantics over the
lower-level constructs. Handles are the lower level, promises are the
higher. Much like pointers and smart pointers.
If ownership means "right to call", and the caller of the coroutine had
>> that right, why should that right be lost without the caller *knowing*
>> about it? What you seem to want is conceptually no different from this:
>>
>> unique_ptr<T> t = make_unique<T>(...);
>> t->TransferOwnership();
>> //t is now empty... somehow.
>>
>> This doesn't work with smart pointers. And I don't know why you want it
>> to work with coroutines. Either way, it seems excessively dangerous.
>>
>
> It's more like this: `t->TransferOwnership(t);`
>
No, that's different. Because you gave it a unique_ptr as an explicit
parameter, there is at least the possibility of a transfer of ownership.
Unlike the `coro` case, where there is no apparent reason for `coro` to
become empty. I'm not saying you couldn't implement it that way; I'm saying
that it's not *apparent* and is therefore not good code.
Also, you missed the `std::move`. Unless you're moving from a reference,
which is a bad idea, as previously discussed (and hopefully will become a
core guideline <https://github.com/isocpp/CppCoreGuidelines/issues/316>).
>
--
---
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_3124_1379333446.1444514584167
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Saturday, October 10, 2015 at 3:39:47 PM UTC-4, TONGARI J wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gm=
ail_quote">2015-10-11 2:14 GMT+08:00 Nicol Bolas <span dir=3D"ltr"><<a h=
ref=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"fSBH7V9vDQAJ=
" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return =
true;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@g=
mail.com</a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,20=
4);border-left-style:solid;padding-left:1ex">On Saturday, October 10, 2015 =
at 12:35:52 PM UTC-4, TONGARI J wrote:<span><blockquote class=3D"gmail_quot=
e" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-colo=
r:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"lt=
r"><div><div class=3D"gmail_quote"><div>```c++</div><div><div>std::coroutin=
e<> fn()</div><div>{</div><div>=C2=A0 =C2=A0 await std::suspend_alway=
s{}; // [1]</div><div>=C2=A0 =C2=A0 await something_takes_the_ownership(<wb=
r>); // [2]</div><div>}</div></div><div>...</div><div>std::coroutine<>=
; coro =3D=C2=A0fn(); // stop at [1], `coro` owns the context</div><div>cor=
o(); // caller - transfer the ownership=C2=A0at [2]</div><div>// now `coro`=
has no associated context</div><div>```</div><div><br></div><div>You can s=
ee that `coro` is the caller, and it's the coroutine that will be trans=
ferred (i.e. what passed into `await_suspend`).</div></div></div></div></bl=
ockquote></span><div><br>I find this code to be rather dubious.<br><br>To w=
hom is the ownership transferred?</div></blockquote><div><br></div><div>Who=
ever wants to execute the continuation.</div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><div>(with this being defined as you do: "the=C2=A0right to execute=
=C2=A0the continuation", but we'll discuss that more later) A thin=
g cannot own itself; there would be no one available to continue it. So the=
only thing this can do is transfer ownership to someone else.<br></div></b=
lockquote><div><br></div><div>A `coroutine` owns the "execution-contex=
t", not itself, it can transfer the context to others.</div></div></di=
v></div></blockquote><div><br>I don't know what you mean by "execu=
tion context".<br><br>If you mean "all of the information needed =
to be able to resume execution", we have a word for that: "corout=
ine". It's a function, a piece of memory representing its stack va=
riables, and whatever other bits of information are needed to That's al=
l a coroutine is: what is needed to resume execution after execution is pau=
sed. So if that's what you mean by "execution context", then =
we seem to be in agreement.<br><br>If you mean something else, well, I'=
m not sure what that would be.<br>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div> <br>=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;b=
order-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:s=
olid;padding-left:1ex"><div>Given that, why should the caller of the corout=
ine be ignorant of said transference? That is, why shouldn't the code l=
ook like this:<br><br><div style=3D"border:1px solid rgb(187,187,187);word-=
wrap:break-word;background-color:rgb(250,250,250)"><code><div><span><span s=
tyle=3D"color:rgb(0,0,0)">std</span><span style=3D"color:rgb(102,102,0)">::=
</span><span style=3D"color:rgb(0,0,0)">coroutine</span><span style=3D"colo=
r:rgb(102,102,0)"><></span><span style=3D"color:rgb(0,0,0)"> fn</span=
><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0=
,0)"><br></span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D=
"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0 await std</span><span style=3D"color:r=
gb(102,102,0)">::</span><span style=3D"color:rgb(0,0,0)">suspend_always</sp=
an><span style=3D"color:rgb(102,102,0)">{};</span><span style=3D"color:rgb(=
0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">// [1]</span><span style=
=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">}</sp=
an><span style=3D"color:rgb(0,0,0)"><br></span></span><span><span style=3D"=
color:rgb(102,102,0)">...</span><span style=3D"color:rgb(0,0,0)"><br>std</s=
pan><span style=3D"color:rgb(102,102,0)">::</span><span style=3D"color:rgb(=
0,0,0)">coroutine</span><span style=3D"color:rgb(102,102,0)"><></span=
><span style=3D"color:rgb(0,0,0)"> coro </span><span style=3D"color:rgb(102=
,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)"> fn</span><span style=
=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(136,0,0)">// stop at [1], `coro` owns the contex=
t</span></span><span style=3D"color:rgb(0,0,0)"><br><br>something_takes_the=
_ownership</span><span style=3D"color:rgb(102,102,0)">(</span><span style=
=3D"color:rgb(0,0,0)"><wbr>std</span><span style=3D"color:rgb(102,102,0)">:=
:</span><span style=3D"color:rgb(0,0,0)">move</span><span style=3D"color:rg=
b(102,102,0)">(</span><span style=3D"color:rgb(0,0,0)">coro</span><span sty=
le=3D"color:rgb(102,102,0)">));</span><span style=3D"color:rgb(0,0,0)"><br>=
<br></span><span style=3D"color:rgb(136,0,0)">//Now, coro is empty.</span><=
/div></code></div><br>I think that makes a lot more sense. It makes it clea=
r to the reader that `coro` is no longer to be used. You can even encapsula=
te it in a factory function, so that nobody can call `fn` directly.<br></di=
v></blockquote><div><br></div><div>Uh, that's just a demo how things wo=
rk. In the "awaiter", what `await_suspend` does=C2=A0is exactly `=
std::move(coro)`.</div></div></div></div></blockquote><div><br>I'm awar=
e of that. I understand that, somewhere in some library code, movement took=
place. `std::move` was called.<br><br>My point is that this is <i>not appa=
rent to the user</i>. They don't know it happened without looking it up=
in documentation.<br><br>In normal code, if you want to move something, th=
e person who currently own it must agree to the move, typically by using `s=
td::move`. If you have a sequence of functions that all take `unique_ptr`, =
each and every one of them must std::move their value into each function ca=
ll. Thus making it clear that ownership is being transferred at each call s=
ite.<br><br>We agree that the function who called the coroutine owns it imm=
ediately after this call. And you want the function who owns the coroutine =
to lose ownership of it, simply by having resumed it.<br><br>That is not a =
transferal of ownership. In a transfer of ownership, the source and destina=
tion both agree that the source is losing ownership and the destination is =
gaining it.<br><br>What you want to do is not <i>give</i> ownership; you wa=
nt to <i>steal</i> it. You had the coroutine arbitrarily decide that the ca=
ller no longer has the right to call it. This code cannot be statically ins=
pected to know that this has happened, not without the coroutine function&#=
39;s implementation.<br><br>I would consider this to be <i>perfidy</i>; cod=
e willfully lying to other code.<br><br>This is also why I consider it a co=
de smell to move from a parameter that is not a value or an rvalue referenc=
e. Either the function moves from it or it doesn't; it shouldn't &q=
uot;sometimes maybe kinda could do so". How can you possibly write saf=
e code if you don't even know whether the object will be valid after ca=
lling it?<br><br>I'm sure you've implemented a coroutine system tha=
t does this. That doesn't make it a good idea.<br><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail=
_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border=
-left-style:solid;padding-left:1ex"><div>This style of code also prevents t=
his:<br><br><div style=3D"border:1px solid rgb(187,187,187);word-wrap:break=
-word;background-color:rgb(250,250,250)"><code><div><span><span style=3D"co=
lor:rgb(0,0,0)">std</span><span style=3D"color:rgb(102,102,0)">::</span><sp=
an style=3D"color:rgb(0,0,0)">coroutine</span><span style=3D"color:rgb(102,=
102,0)"><></span><span style=3D"color:rgb(0,0,0)"> fn</span><span sty=
le=3D"color:rgb(102,102,0)">()</span><span style=3D"color:rgb(0,0,0)"><br><=
/span><span style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb=
(0,0,0)"><br>=C2=A0 =C2=A0 await std</span><span style=3D"color:rgb(102,102=
,0)">::</span><span style=3D"color:rgb(0,0,0)">suspend_always</span><span s=
tyle=3D"color:rgb(102,102,0)">{};</span><span style=3D"color:rgb(0,0,0)"> <=
/span><span style=3D"color:rgb(136,0,0)">// [1]</span><span style=3D"color:=
rgb(0,0,0)"><br>=C2=A0 =C2=A0 await something_takes_the_ownership</span><sp=
an style=3D"color:rgb(102,102,0)">(<wbr>);</span><span style=3D"color:rgb(0=
,0,0)"> </span><span style=3D"color:rgb(136,0,0)">// [2]</span><span style=
=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102,102,0)">}</sp=
an><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(102=
,102,0)">...</span><span style=3D"color:rgb(0,0,0)"><br>std</span><span sty=
le=3D"color:rgb(102,102,0)">::</span><span style=3D"color:rgb(0,0,0)">corou=
tine</span><span style=3D"color:rgb(102,102,0)"><></span><span style=
=3D"color:rgb(0,0,0)"> coro </span><span style=3D"color:rgb(102,102,0)">=3D=
</span><span style=3D"color:rgb(0,0,0)"> fn</span><span style=3D"color:rgb(=
102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(136,0,0)">// stop at [1], `coro` owns the context</span><span=
style=3D"color:rgb(0,0,0)"><br>coro</span><span style=3D"color:rgb(102,102=
,0)">();</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(136,0,0)">// caller - transfer the ownership at [2]</span><span style=
=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(136,0,0)">// now =
`coro` has no associated context</span></span><span style=3D"color:rgb(0,0,=
0)"><br>coro</span><span style=3D"color:rgb(102,102,0)">();</span><span sty=
le=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,0,0)">//Well, =
it looked like a valid object...</span><span style=3D"color:rgb(0,0,0)"><br=
></span></div></code></div><br>By having your `std::coroutine` (which is a =
coroutine promise, and therefore not the same thing as `coroutine_handle`) =
implement move semantics, you make it clear that ownership of `coro` has be=
en transferred to someone else. It's not implicitly gone; it's expl=
icitly gone.<br></div></blockquote><div><br></div><div>It does implement mo=
ve semantics, and no, it's not=C2=A0a coroutine promise, it's a cor=
outine-return-type,</div></div></div></div></blockquote><div><br>By P0057, =
the return type of a coroutine <i>must</i> be a coroutine promise, as defin=
ed in 18.11.4. That is what the "coroutine-return-type" is called=
..<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div>but you're right that it's=
not the same as `coroutine_handle` because the latter doesn't provide =
RAII semantic and thus is not safe to be a coroutine-return-type.</div></di=
v></div></div></blockquote><div><br>That is <i>not</i> why coroutines don&#=
39;t directly return a `coroutine_handle`. The point of the distinction bet=
ween coroutine promises and coroutine handles is to allow users to build hi=
gher-level semantics over the lower-level constructs. Handles are the lower=
level, promises are the higher. Much like pointers and smart pointers.<br>=
<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,2=
04);border-left-style:solid;padding-left:1ex"><div>If ownership means "=
;right to call", and the caller of the coroutine had that right, why s=
hould that right be lost without the caller <i>knowing</i> about it? What y=
ou seem to want is conceptually no different from this:<br><br><div style=
=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-color=
:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,0)">unique_ptr</=
span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"color:r=
gb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">></span><span st=
yle=3D"color:rgb(0,0,0)"> t </span><span style=3D"color:rgb(102,102,0)">=3D=
</span><span style=3D"color:rgb(0,0,0)"> make_unique</span><span style=3D"c=
olor:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</span><s=
pan style=3D"color:rgb(102,102,0)">>(...);</span><span style=3D"color:rg=
b(0,0,0)"><br>t</span><span style=3D"color:rgb(102,102,0)">-></span><spa=
n style=3D"color:rgb(102,0,102)">TransferOwnership</span><span style=3D"col=
or:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"><br></span><s=
pan style=3D"color:rgb(136,0,0)">//t is now empty... somehow.</span></div><=
/code></div><br>This doesn't work with smart pointers. And I don't =
know why you want it to work with coroutines. Either way, it seems excessiv=
ely dangerous.<br></div></blockquote><div><br></div><div>It's more like=
this: `t->TransferOwnership(t);`</div></div></div></div></blockquote><d=
iv><br>No, that's different. Because you gave it a unique_ptr as an exp=
licit parameter, there is at least the possibility of a transfer of ownersh=
ip. Unlike the `coro` case, where there is no apparent reason for `coro` to=
become empty. I'm not saying you couldn't implement it that way; I=
'm saying that it's not <i>apparent</i> and is therefore not good c=
ode.<br><br>Also, you missed the `std::move`. Unless you're moving from=
a reference, which is a bad idea, as previously discussed (and hopefully w=
ill <a href=3D"https://github.com/isocpp/CppCoreGuidelines/issues/316">beco=
me a core guideline</a>).<br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">
</blockquote>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3124_1379333446.1444514584167--
------=_Part_3123_1164530807.1444514584166--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 15:39:58 -0700 (PDT)
Raw View
------=_Part_735_985725714.1444516798727
Content-Type: multipart/alternative;
boundary="----=_Part_736_536094376.1444516798729"
------=_Part_736_536094376.1444516798729
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 3:03:04 PM UTC-7, Nicol Bolas wrote:
>
> By P0057, the return type of a coroutine *must* be a coroutine promise,
> as defined in 18.11.4. That is what the "coroutine-return-type" is called.
>
Nicol:
If P0057 states so, it is my mistake and I need to fix it.
The return type of a coroutine has a very boring name: "coroutine return
type". There is no semantics associated with it.
It could be 'void', 'int', 'float', whatever, as long as there is a
corresponding specialization of coroutine_traits so that compiler knows
what to do with it.
The predefined primary template for coroutine_traits states that:
template <typename R, typename... Args>
struct coroutine_traits {
using promise_type = typename R::promise_type;
};
This primary template allows to define coroutine return types without
having to specialize coroutine_traits, by providing an member
struct/typedef named promise_type, as in:
template <typename T>
struct my_generator {
struct promise_type {
auto get_return_object() { return my_generator{this}; }
auto initial_suspend() { return true; }
auto final_suspend() { return true; }
void yield_value(T value) { current_value = value; }
T current_value;
};
bool move_next() {
coro.resume();
return !coro.done();
}
T current_value() { return coro.promise().current_value; }
~my_generator() { coro.destroy(); }
private:
explicit my_generator(promise_type* myPromise)
: coro(coroutine_handle<promise_type>::from_promise(myPromise)) {}
coroutine_handle<promise_type> coro;
};
*coroutine frame* is an object which is an aggregation of all objects with
automatic storage duration in the coroutine body that persists across
suspend points including the *coroutine promise*.
strongly typed *coroutine_handle<P>* pointing at the coroutine frame will
give access to the *coroutine promise* and will allow to manipulate it as
you can see my_generator is doing.
So, to summarize, the terminology in P0057 is:
coroutine = function with suspend points
coroutine return object = what coroutine returns (it may have a
coroutine_handle inside or not. Depends on the library writer)
coroutine frame = an object with all the coroutine state that needs to
persist across suspends (could be on the heap or not)
coroutine_handle = a pointer to a coroutine frame
coroutine_promise = a special automatic object through which compiler
communicates with the library to figure out the semantics of the coroutine
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_736_536094376.1444516798729
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, October 10, 2015 at 3:03:04 PM UTC-7,=
Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0=
px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bor=
der-left-width: 1px; border-left-style: solid;"><div>By P0057, the return t=
ype of a coroutine <i>must</i> be a coroutine promise, as defined in 18.11.=
4. That is what the "coroutine-return-type" is called.</div></blo=
ckquote><div><br></div><div>Nicol:</div><div><br></div><div>If P0057 states=
so, it is my mistake and I need to fix it.</div><div>The return type of a =
coroutine has a very boring name: "coroutine return type". There =
is no semantics associated with it. </div><div>It could be 'void', =
'int', 'float', whatever, as long as there is a correspondi=
ng specialization of coroutine_traits so that compiler knows what to do wit=
h it.</div><div><br></div><div>The predefined primary template for coroutin=
e_traits states that:</div><div><br></div><div><p><font color=3D"#0000ff" f=
ace=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">template</font>=
</font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" si=
ze=3D"2"> <</font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">typename</font></font></font><font fa=
ce=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> </font></fon=
t><font color=3D"#2b91af" face=3D"Consolas" size=3D"2"><font color=3D"#2b91=
af" face=3D"Consolas" size=3D"2"><font color=3D"#2b91af" face=3D"Consolas" =
size=3D"2">R</font></font></font><font face=3D"Consolas" size=3D"2"><font f=
ace=3D"Consolas" size=3D"2">, </font></font><font color=3D"#0000ff" face=3D=
"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">=
<font color=3D"#0000ff" face=3D"Consolas" size=3D"2">typename</font></font>=
</font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2=
">... </font></font><font color=3D"#2b91af" face=3D"Consolas" size=3D"2"><f=
ont color=3D"#2b91af" face=3D"Consolas" size=3D"2"><font color=3D"#2b91af" =
face=3D"Consolas" size=3D"2">Args</font></font></font><font face=3D"Consola=
s" size=3D"2"><font face=3D"Consolas" size=3D"2">></font></font></p><fon=
t face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">
</font></font><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font co=
lor=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"></font></font></font><p><font color=3D"#0000ff" fa=
ce=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">struct</font></=
font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=
=3D"2"> </font></font><font color=3D"#2b91af" face=3D"Consolas" size=3D"2">=
<font color=3D"#2b91af" face=3D"Consolas" size=3D"2"><font color=3D"#2b91af=
" face=3D"Consolas" size=3D"2">coroutine_traits</font></font></font><font f=
ace=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> {</font></f=
ont></p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"=
2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0 using</font></font></fon=
t><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> </=
font></font><font color=3D"#2b91af" face=3D"Consolas" size=3D"2"><font colo=
r=3D"#2b91af" face=3D"Consolas" size=3D"2"><font color=3D"#2b91af" face=3D"=
Consolas" size=3D"2">promise_type</font></font></font><font face=3D"Consola=
s" size=3D"2"><font face=3D"Consolas" size=3D"2"> =3D </font></font><font c=
olor=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"=
2">typename</font></font></font><font face=3D"Consolas" size=3D"2"><font fa=
ce=3D"Consolas" size=3D"2"> </font></font><font color=3D"#2b91af" face=3D"C=
onsolas" size=3D"2"><font color=3D"#2b91af" face=3D"Consolas" size=3D"2"><f=
ont color=3D"#2b91af" face=3D"Consolas" size=3D"2">R</font></font></font><f=
ont face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">::</fon=
t></font><font color=3D"#2b91af" face=3D"Consolas" size=3D"2"><font color=
=3D"#2b91af" face=3D"Consolas" size=3D"2"><font color=3D"#2b91af" face=3D"C=
onsolas" size=3D"2">promise_type</font></font></font><font face=3D"Consolas=
" size=3D"2"><font face=3D"Consolas" size=3D"2">;</font></font></p><font fa=
ce=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">
<p>};</p></font><p><br></p></font><p><br></p></div><div>This primary templa=
te allows to define coroutine return types without having to specialize cor=
outine_traits, by providing an member struct/typedef named promise_type, as=
in:</div><div><br></div><div><p><font color=3D"#0000ff" face=3D"Consolas" =
size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=
=3D"#0000ff" face=3D"Consolas" size=3D"2">template</font></font></font><fon=
t face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> <</fo=
nt></font><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=
=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"C=
onsolas" size=3D"2">typename</font></font></font><font face=3D"Consolas" si=
ze=3D"2"><font face=3D"Consolas" size=3D"2"> T></font></font></p><font f=
ace=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">
</font></font><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font co=
lor=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"></font></font></font><p><font color=3D"#0000ff" fa=
ce=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">=C2=A0 struct</=
font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consola=
s" size=3D"2"> my_generator {</font></font></p><font face=3D"Consolas" size=
=3D"2"><font face=3D"Consolas" size=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0 struct</font></fon=
t></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D=
"2"> promise_type {</font></font></p><font face=3D"Consolas" size=3D"2"><fo=
nt face=3D"Consolas" size=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto</=
font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consola=
s" size=3D"2"> get_return_object() { </font></font><font color=3D"#0000ff" =
face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">return</font></=
font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=
=3D"2"> my_generator{</font></font><font color=3D"#0000ff" face=3D"Consolas=
" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font col=
or=3D"#0000ff" face=3D"Consolas" size=3D"2">this</font></font></font><font =
face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">}; }</font>=
</font></p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=
=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto</=
font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consola=
s" size=3D"2"> initial_suspend() { </font></font><font color=3D"#0000ff" fa=
ce=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">return</font></=
font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=
=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">=
<font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff=
" face=3D"Consolas" size=3D"2">true</font></font></font><font face=3D"Conso=
las" size=3D"2"><font face=3D"Consolas" size=3D"2">; }</font></font></p><fo=
nt face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 auto</=
font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consola=
s" size=3D"2"> final_suspend() { </font></font><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"=
2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">return</font></font=
></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"=
2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><fon=
t color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" fa=
ce=3D"Consolas" size=3D"2">true</font></font></font><font face=3D"Consolas"=
size=3D"2"><font face=3D"Consolas" size=3D"2">; }</font></font></p><font f=
ace=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 void</=
font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consola=
s" size=3D"2"> yield_value(T value) { current_value =3D value; }</font></fo=
nt></p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2=
">
<p> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 T current_value;</p>
<p> =C2=A0=C2=A0=C2=A0 };</p>
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0 bool</font></font>=
</font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2=
"> move_next() {</font></font></p><font face=3D"Consolas" size=3D"2"><font =
face=3D"Consolas" size=3D"2"><p>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0coro.re=
sume();</p>
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return=
</font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Conso=
las" size=3D"2"> !coro.done();</font></font></p><font face=3D"Consolas" siz=
e=3D"2"><font face=3D"Consolas" size=3D"2">
<p> =C2=A0=C2=A0=C2=A0 }</p>
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> =C2=A0=C2=A0=C2=A0 T current_value() { </font></font><font col=
or=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D=
"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">=
return</font></font></font><font face=3D"Consolas" size=3D"2"><font face=3D=
"Consolas" size=3D"2"> coro.promise().current_value; }</font></font></p><fo=
nt face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">
<p> =C2=A0=C2=A0=C2=A0 ~my_generator() { coro.destroy(); }</p>
</font></font><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font co=
lor=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"></font></font></font><p><font color=3D"#0000ff" fa=
ce=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">private</font><=
/font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" siz=
e=3D"2">:</font></font></p><font face=3D"Consolas" size=3D"2"><font face=3D=
"Consolas" size=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0 explicit</font></font></=
font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">=
my_generator(promise_type* myPromise)</font></font></p><font face=3D"Conso=
las" size=3D"2"><font face=3D"Consolas" size=3D"2"><p>=C2=A0=C2=A0=C2=A0 =
=C2=A0: coro(coroutine_handle<promise_type>::from_promise(myPromise))=
{}</p>
<p>=C2=A0=C2=A0 coroutine_handle<promise_type> coro;</p>
<p>};</p><p><br></p><p><strong>coroutine frame</strong> is an object which=
=C2=A0is an aggregation of=C2=A0all objects with automatic storage duration=
in the coroutine body that persists across suspend points including the <s=
trong>coroutine promise</strong>.</p><p><br></p><p>strongly typed <strong>c=
oroutine_handle<P></strong> pointing at the coroutine frame will give=
access to the <strong>coroutine promise</strong> and will allow to manipul=
ate it as you can see my_generator is doing.</p><p><br></p><p>So, to summar=
ize, the terminology in P0057 is:</p><p><br></p><p>coroutine =3D function w=
ith suspend points</p><p>coroutine return object =3D what coroutine returns=
(it may have a coroutine_handle inside or not. Depends on the library writ=
er)</p><p>coroutine frame =3D an object with all the coroutine state that n=
eeds to persist across suspends (could be on the heap or not)</p><p>corouti=
ne_handle =3D a pointer to a coroutine frame</p><p>coroutine_promise =3D a =
special automatic object through which compiler communicates with the libra=
ry to figure out the semantics=C2=A0of the coroutine</p><p><br></p><p><br><=
/p><p><br></p></font></font></div><div><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-=
color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid=
;">
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_736_536094376.1444516798729--
------=_Part_735_985725714.1444516798727--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 10 Oct 2015 17:34:27 -0700 (PDT)
Raw View
------=_Part_3265_1255848183.1444523667457
Content-Type: multipart/alternative;
boundary="----=_Part_3266_860055496.1444523667457"
------=_Part_3266_860055496.1444523667457
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 6:39:58 PM UTC-4, Gor Nishanov wrote:
>
> On Saturday, October 10, 2015 at 3:03:04 PM UTC-7, Nicol Bolas wrote:
>>
>> By P0057, the return type of a coroutine *must* be a coroutine promise,
>> as defined in 18.11.4. That is what the "coroutine-return-type" is called.
>>
>
> Nicol:
>
> If P0057 states so, it is my mistake and I need to fix it.
>
OK, so the promise type can be the return value, and by default it is, but
it does not *have* to be.
I'm not sure what the point of the distinction is. Especially since
coroutine_traits is specialized based on something that is hardly unique to
a particular coroutine function: the function's signature. Which means
every function of the form `int()` will have the exact same promise type,
no matter what.
It seems much safer to just return the promise itself.
Also, I was reading through the definition of await, and I realized that it
wasn't doing what I thought it was supposed to be doing.
I assumed that the point of await was to halt the current function's
execution until the process in the await-expr had completed (ie: either hit
its final return or yielded an actual value). Well, I looked at how `await`
is unpacked, and I realized that... there's no loop.
It's a single conditional check. So if I execute a coroutine, and it comes
back as "not ready" due to `await`ing on an async process, what will stop
the caller of the coroutine from simply calling it again, thus causing it
to execute past the suspend point? After all, execution will resume at
exactly the `suspend-resume-point`. And this point is always after the
conditional. So the condition won't even be checked.
So do I have to do something like `while(await <expr>)` to actually wait on
something? Or have I misunderstood something?
--
---
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_3266_860055496.1444523667457
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, October 10, 2015 at 6:39:58 PM UTC-4, Gor Nis=
hanov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">O=
n Saturday, October 10, 2015 at 3:03:04 PM UTC-7, Nicol Bolas wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1=
ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-sty=
le:solid"><div>By P0057, the return type of a coroutine <i>must</i> be a co=
routine promise, as defined in 18.11.4. That is what the "coroutine-re=
turn-type" is called.</div></blockquote><div><br></div><div>Nicol:</di=
v><div><br></div><div>If P0057 states so, it is my mistake and I need to fi=
x it.</div></div></blockquote><div dir=3D"ltr"><br>OK, so the promise type =
can be the return value, and by default it is, but it does not <i>have</i> =
to be.<br><br>I'm not sure what the point of the distinction is. Especi=
ally since coroutine_traits is specialized based on something that is hardl=
y unique to a particular coroutine function: the function's signature. =
Which means every function of the form `int()` will have the exact same pro=
mise type, no matter what.<br><br>It seems much safer to just return the pr=
omise itself.<div><br>Also, I was reading through the definition of await, =
and I realized that it wasn't doing what I thought it was supposed to b=
e doing.<br><br>I assumed that the point of await was to halt the current f=
unction's execution until the process in the await-expr had completed (=
ie: either hit its final return or yielded an actual value). Well, I looked=
at how `await` is unpacked, and I realized that... there's no loop.<br=
><br>It's a single conditional check. So if I execute a coroutine, and =
it comes back as "not ready" due to `await`ing on an async proces=
s, what will stop the caller of the coroutine from simply calling it again,=
thus causing it to execute past the suspend point? After all, execution wi=
ll resume at exactly the `suspend-resume-point`. And this point is always a=
fter the conditional. So the condition won't even be checked.<br><br>So=
do I have to do something like `while(await <expr>)` to actually wai=
t on something? Or have I misunderstood something?<br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3266_860055496.1444523667457--
------=_Part_3265_1255848183.1444523667457--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sat, 10 Oct 2015 18:29:25 -0700 (PDT)
Raw View
------=_Part_806_732753113.1444526965611
Content-Type: multipart/alternative;
boundary="----=_Part_807_1992163061.1444526965619"
------=_Part_807_1992163061.1444526965619
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 5:34:27 PM UTC-7, Nicol Bolas wrote:
>
> OK, so the promise type can be the return value, and by default it is, but
> it does not *have* to be.
>
Look at the picture on slide 37 of
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4287.pdf
Given a function like this:
R foo(whatever...) { ... await ... }
Compiler instantiates
coroutine_traits<R,whatever...> <-- coroutine traits for 'foo', let's
call this type CT
from these traits compiler grabs
CT::promise_type <-- this is coroutine promise type, let's call it P
Then logically, after the open curly, it injects P $p; <-- $p is coroutine
promise.
Then it transform the body roughly in this way:
R foo(whatever...) {P $p; R $result = $p.get_return_object(); ... await
.... }
$result is what will get returned to the caller the first time coroutine
suspends. These steps are also described in P0057/8.4.4 if you want more
precision.
R is coroutine return type. P is a promise type. Type P is discovered when
we instantiate coroutine_traits<R,whatever...>.
Normally R != P.
>> So do I have to do something like `while(await <expr>)` to actually wait
on something? Or have I misunderstood something?
If it makes it easier, you can watch last year CppCon presentation from
about 10 minutes mark. I will slowly go over how awaitables work:
https://youtu.be/KUhSjfSbINE?t=597
--
---
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_807_1992163061.1444526965619
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, October 10, 2015 at 5:34:27 PM UTC-7,=
Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0=
px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bor=
der-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">OK, so the=
promise type can be the return value, and by default it is, but it does no=
t <i>have</i> to be.<br></div></blockquote><div><br></div><div>Look at the =
picture on slide 37 of <a href=3D"http://www.open-std.org/jtc1/sc22/wg21/do=
cs/papers/2014/n4287.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/paper=
s/2014/n4287.pdf</a>=C2=A0</div><div><br></div><div>Given a function like t=
his:</div><div><br></div><div>=C2=A0=C2=A0=C2=A0 R foo(whatever...) { ... a=
wait ... }</div><div><br></div><div>Compiler instantiates</div><div><br></d=
iv><div>=C2=A0=C2=A0=C2=A0 coroutine_traits<R,whatever...> <-- cor=
outine traits for 'foo', let's call this type CT</div><div><br>=
</div><div>from=C2=A0these traits=C2=A0compiler grabs</div><div><br></div><=
div>=C2=A0=C2=A0=C2=A0 CT::promise_type <-- this is coroutine promise ty=
pe, let's call it P</div><div><br></div><div>Then logically, after the =
open curly, it injects P $p; <-- $p is coroutine promise.</div><div><br>=
</div><div>Then it transform the body roughly in this way:</div><div><br></=
div><div><div>=C2=A0=C2=A0=C2=A0 R foo(whatever...) {P $p; R=C2=A0$result =
=3D=C2=A0$p.get_return_object();=C2=A0... await ... }</div><div><br></div><=
div>$result is what will get returned to the caller the first time coroutin=
e suspends. These steps are also described in P0057/8.4.4 if you want more =
precision.</div><div>R is coroutine return type. P is a promise type. Type =
P is discovered when we instantiate coroutine_traits<R,whatever...>.<=
/div><div>Normally R !=3D P.</div><div><br></div></div><div>>> So do =
I have to do something like `while(await <expr>)` to actually wait on=
something? Or have I misunderstood something?</div><div><br></div><div>If =
it makes it easier, you can watch last year CppCon presentation from about =
10 minutes mark. I will slowly go over how awaitables work:</div><div><br><=
/div><div><a href=3D"https://youtu.be/KUhSjfSbINE?t=3D597">https://youtu.be=
/KUhSjfSbINE?t=3D597</a></div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_807_1992163061.1444526965619--
------=_Part_806_732753113.1444526965611--
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Sun, 11 Oct 2015 07:10:06 +0200
Raw View
--001a1140980e029da20521cd3b8b
Content-Type: text/plain; charset=UTF-8
2015-10-11 0:03 GMT+02:00 Nicol Bolas <jmckesson@gmail.com>:
> A `coroutine` owns the "execution-context", not itself, it can transfer
>> the context to others.
>>
>
> I don't know what you mean by "execution context".
>
> If you mean "all of the information needed to be able to resume
> execution", we have a word for that: "coroutine". It's a function, a piece
> of memory representing its stack variables, and whatever other bits of
> information are needed to That's all a coroutine is: what is needed to
> resume execution after execution is paused. So if that's what you mean by
> "execution context", then we seem to be in agreement.
>
what about this definition:
execution context == single/individual path of execution inside a program;
an application might have more than one paths
an execution context can be characterized by instruction pointer + set of
general CPU registers and the stack (stackless coroutines own a degenerated
form == activation record, used to store local variables)
a coroutine can be understood as the interaction of two execution contexts,
a coroutine consists of a caller and a callee, which are thigh coupled. the
caller execution context resumes only the execution context of the callee,
while the callee can only suspend to the caller. data might be transferred
in both directions.
of course an execution context can play multiple roles, for instance the
execution context of the callee might play the role of a caller for a
stacked coroutine (-> coroutine launched inside a coroutine). then the
execution context of the callee from the external coroutine becomes that
caller execution context for the internal/stacked coroutine.
generators are a special kind of coroutines - data flows only in one
direction (callee -> caller).
fibers can be understood a loosely coupled execution contexts - a fiber
does not know its predecessor and successor. data is not directly exchanged
between fibers.
delimited continuations could be defined in this way too (with a more
complex pattern of interactions/data transfer).
--
---
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/.
--001a1140980e029da20521cd3b8b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-11 0:03 GMT+02:00 Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:j=
mckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div><div class=3D"gmail_quote"><div>A `coroutine` owns the =
"execution-context", not itself, it can transfer the context to o=
thers.</div></div></div></div></blockquote><div><br>I don't know what y=
ou mean by "execution context".<br><br>If you mean "all of t=
he information needed to be able to resume execution", we have a word =
for that: "coroutine". It's a function, a piece of memory rep=
resenting its stack variables, and whatever other bits of information are n=
eeded to That's all a coroutine is: what is needed to resume execution =
after execution is paused. So if that's what you mean by "executio=
n context", then we seem to be in agreement.<br></div></blockquote></d=
iv><br></div><div class=3D"gmail_extra">what about this definition:<br><br>=
</div><div class=3D"gmail_extra">execution context =3D=3D single/individual=
path of execution inside a program; an application might have more than on=
e paths<br></div><div class=3D"gmail_extra">an execution context can be cha=
racterized by instruction pointer + set of general CPU registers and the st=
ack (stackless coroutines own a degenerated form =3D=3D activation record, =
used to store local variables)<br><br></div><div class=3D"gmail_extra">a co=
routine can be understood as the interaction of two execution contexts, a c=
oroutine consists of a caller and a callee, which are thigh coupled. the ca=
ller execution context resumes only the execution context of the callee, wh=
ile the callee can only suspend to the caller. data might be transferred in=
both directions.<br></div><div class=3D"gmail_extra">of course an executio=
n context can play multiple roles, for instance the execution context of th=
e callee might play the role of a caller for a stacked coroutine (-> cor=
outine launched inside a coroutine). then the execution context of the call=
ee from the external coroutine becomes that caller execution context for th=
e internal/stacked coroutine.<br></div><div class=3D"gmail_extra">generator=
s are a special kind of coroutines - data flows only in one direction (call=
ee -> caller).<br></div><div class=3D"gmail_extra"><br></div><div class=
=3D"gmail_extra">fibers can be understood a loosely coupled execution conte=
xts - a fiber does not know its predecessor and successor. data is not dire=
ctly exchanged between fibers.<br><br></div><div class=3D"gmail_extra">deli=
mited continuations could be defined in this way too (with a more complex p=
attern of interactions/data transfer).<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1140980e029da20521cd3b8b--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Sun, 11 Oct 2015 13:48:47 +0800
Raw View
--047d7bd74b823278470521cdc4df
Content-Type: text/plain; charset=UTF-8
Hi Gor,
2015-10-11 4:37 GMT+08:00 Gor Nishanov <gornishanov@gmail.com>:
> Hi Tongari:
>
> Low level APIs need to worry about efficiency, high level APIs need to
> worry about beauty of abstraction and safety while using low level APIs to
> do it efficiently.
> It is possible to give coroutine_handle a unique_ptr like semantic, but,
> now we pessimized performance in at least three areas:
>
> 1) mandatory extra dereference in coroutine observers
> 2) ownership transfer. Now there is always a = nullptr whenever I move it
> around
> 3) now there must be a mandatory branch in the destructor if (_Ptr)
> coro.destroy()
>
All true.
> Moreover, we gave the higher-level semantics to the coroutine_handle. If
> that does not match what the library wants to do, it now needs to add code
> to suppress that behavior, (for example if it does not want ownership
> semantic, it should zero out the handle before the destruction).
>
> coroutine_handle is not for the end user. It is a sharp tool for the
> library writer. Moreover it is a compiler provided tool. If I don't like
> the library, I can write my own. If I don't like what compiler gives me, I
> am not going to write a new compiler.
>
> Currently, it is a raw pointer. You cannot get any more efficient than
> that. It is fully devoid of higher level semantics. As a library writer you
> decide what it means. You decide what trade-offs to do and what efficiency
> you want to sacrifice for ease of use. I as a compiler don't want to make
> any trade-offs. I give pretty syntactic sugar to the end-user and a bunch
> of sharp knives to the library developer.
>
> I am open to any suggestions how to make the library adaptation layers
> more library writer friendly as long as I don't have to sacrifice
> performance in space or time.
>
Bear in mind that the coroutine-promises and the awaitables could be
written by different people in different libraries, there must exist a
protocol for them to collaborate safely without knowing each other.
Something like "generator" is really a special case, where the promise also
controls the awaitable (i.e. yield_value). For other async-result, we need
the safe semantic anyway.
Consider my earlier example:
```c++
std::future<void> f()
{
Resource res(...);
await std::suspend_always{};
}
```
Do you really think that it's better to have f() leak memory & resource by
default? I don't think so.
And that's not a contrived example, I do do things like that for
cascading-cancellation of tasks in dependency-graph.
With RAII, the cancellation in one node propagates to its dependants
automatically, without exceptions.
Without RAII, to provide the similar behavior, you have to throw exception
that will be catch by its dependants and then throw it again and catch that
in the dependants-of-dependants and so on...which is less performant.
> *On keywords:*
>
> It is not about keywords, correct? P0071 offers a magic std::await and
> std::yield functions as an alternative.
> Your concern is with design point that P0054 requires that every suspend
> point in a function needs to be explicitly marked whether with a keyword or
> magic function.
>
> I have no objections to exploring whether in the future we may get
> "automatically awaited awaitables" or async functions as you suggested in
> your proposal on the github. Sure thing. Go right ahead. Should we wait and
> not standardize coroutines while this exploration is going on?
>
> There reason I added the section about it in P0054 was to show that such
> exploration is possible in the future. It should not stop progress on this
> proposal.
>
What if the future exploration is not compatible with the current design?
that's my concern.
*On awaitable return_value*
>
> I store a reference to the expression (lvalue or temporary on the
> coroutine frame) and give a chance to consumer, potentially running on a
> different thread to observe it before semicolon at the end of full
> expression destroys the value (or leaving the scope and stopping at final
> suspend destroys the lvalue that I was trying to return)
>
I kinda get the idea, but how can the consumer notify the promise that it
takes the value?
```c++
auto val = await future;
```
How can the future know the value is now assigned to val so the coroutine
can go on and destroy?
Are you relying on copy-ellision here and the await_resume must return the
value and not a rv-ref to it?
> *On final_suspend*
>
> I am afraid I cannot answer that without pasting here what I've written in
> P0054. If one of the steps described in P0054 is unclear. Ask me, why Y
> follows from X. Otherwise, I am not sure how I can help.
>
It was pasted in my reply to Nicol Bolas, here it is again:
What is the difference between this:
```c++
auto final_suspend()
{
struct awaiter
{
promise_type * me;
bool await_ready() { return false; }
void await_resume() {}
bool await_suspend(coroutine_handle<>) {
auto need_suspending = (me->decrement_refcount() > 0);
return need_suspending;
}
};
return awaiter{this};
}
```
and this:
```c++
bool final_suspend()
{
auto need_suspending = (decrement_refcount() > 0);
return need_suspending;
}
```
? In my understanding, it only matters if `await_suspend` tends to execute
the continuation before it returns, but in the example, it's not the case,
I don't see why making the coroutine resumable matters before calling
`await_suspend` here.
--
---
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/.
--047d7bd74b823278470521cdc4df
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Gor,<br><div class=3D"gmail_extra"><br><div class=3D"gm=
ail_quote">2015-10-11 4:37 GMT+08:00 Gor Nishanov <span dir=3D"ltr"><<a =
href=3D"mailto:gornishanov@gmail.com" target=3D"_blank">gornishanov@gmail.c=
om</a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>Hi Tongari:</d=
iv><div><br></div><div>Low level APIs need to worry about efficiency, high =
level APIs need to worry about beauty of abstraction and safety while using=
low level APIs to do it efficiently.</div><div>It is possible to give coro=
utine_handle a unique_ptr like semantic, but, now we pessimized performance=
in at least three areas:</div><div><br></div><div>1) mandatory extra deref=
erence in coroutine observers</div><div>2) ownership transfer. Now there is=
always a =3D nullptr whenever I move it around</div><div>3) now there must=
be a mandatory branch in the destructor if (_Ptr) coro.destroy()</div></di=
v></blockquote><div><br></div><div>All true.</div><div>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wid=
th:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div>Moreover, we gave the higher-level semantics=
to the coroutine_handle. If that does not match what the library wants to =
do,=C2=A0it=C2=A0now needs to add code to suppress that behavior, (for exam=
ple if=C2=A0it does not want ownership semantic,=C2=A0it should zero out th=
e handle before the destruction).</div><div><br></div><div>coroutine_handle=
is not for the end user. It is a sharp tool for the library writer. Moreov=
er it is a compiler provided tool. If I don't like the library, I can w=
rite my own. If I don't like what compiler gives me, I am not going to =
write a new compiler.</div><div><br></div><div>Currently, it is a raw point=
er. You cannot get any more efficient than that. It is fully devoid of high=
er level semantics. As a library writer you decide what it means. You decid=
e what trade-offs to do and what efficiency you want to sacrifice for ease =
of use. I as a compiler don't want to make any trade-offs. I give prett=
y syntactic sugar to the end-user and=C2=A0a bunch of sharp knives to the l=
ibrary developer.</div><div><br></div><div>I am open to any suggestions how=
to make the library adaptation layers more library writer friendly as long=
as I don't have to sacrifice performance in space or time.</div></div>=
</blockquote><div><br></div><div>Bear in mind that the coroutine-promises a=
nd the awaitables could be written by different people in different librari=
es, there must exist a protocol for them to collaborate safely without know=
ing each other. Something like "generator" is=C2=A0really=C2=A0a =
special case, where the promise also controls the awaitable (i.e. yield_val=
ue). For other async-result, we need the safe semantic anyway.</div><div><b=
r></div><div>Consider my earlier example:</div><div><br></div><div>```c++</=
div>std::future<void> f()</div><div class=3D"gmail_quote">{</div><div=
class=3D"gmail_quote">=C2=A0 =C2=A0 Resource res(...);</div><div class=3D"=
gmail_quote">=C2=A0 =C2=A0=C2=A0await std::suspend_always{};</div><div clas=
s=3D"gmail_quote">}</div><div class=3D"gmail_quote">```</div><div class=3D"=
gmail_quote"><br></div><div class=3D"gmail_quote">Do you really think that =
it's better to have f() leak memory & resource by default? I don=
9;t think so.</div><div class=3D"gmail_quote">And that's not a contrive=
d example, I do do things like that for cascading-cancellation of tasks in =
dependency-graph.</div><div class=3D"gmail_quote">With RAII, the cancellati=
on in one node propagates to its dependants automatically, without exceptio=
ns.</div><div class=3D"gmail_quote">Without RAII, to provide the similar be=
havior, you have to throw exception that will be catch by its dependants an=
d then throw it again and catch that in the=C2=A0dependants-of-dependants a=
nd so on...which is less performant.</div><div class=3D"gmail_quote"><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div><strong>On ke=
ywords:</strong></div><div><br></div><div>It is not about keywords, correct=
? P0071 offers a magic std::await and std::yield functions as an alternativ=
e.</div><div>Your concern is with design point that P0054 requires that eve=
ry suspend point in=C2=A0a function needs to be explicitly marked whether w=
ith a keyword or magic function. </div><div><br></div><div>I have no object=
ions=C2=A0to exploring whether in the future we may get "automatically=
awaited awaitables" or async functions as you suggested in your propo=
sal on the github. Sure thing. Go right ahead. Should we wait and not stand=
ardize coroutines while this exploration is going on?<br><br>There reason=
=C2=A0I added the section about it in P0054 was to show that such explorati=
on is possible in the future. It should not stop progress on this proposal.=
</div></div></blockquote><div><br></div><div>What if the future exploration=
is not compatible with the current design? that's my concern.</div><di=
v><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-s=
tyle:solid;padding-left:1ex"><div dir=3D"ltr"><div><strong>On awaitable ret=
urn_value</strong></div><div><br></div><div>I store=C2=A0a reference to the=
expression (lvalue or temporary on the coroutine frame) and give a chance =
to consumer, potentially running on a different thread to observe it before=
semicolon at the end of full expression destroys the value (or leaving the=
scope and stopping at final suspend destroys the lvalue that I was trying =
to return)</div></div></blockquote><div><br></div><div>I kinda get the idea=
, but how can the consumer notify the promise that it takes the value?</div=
><div><br></div><div>```c++</div><div>auto val =3D await future;</div><div>=
```</div><div><br></div><div>How can the future know the value is now assig=
ned to val so the coroutine can go on and destroy?</div><div>Are you relyin=
g on copy-ellision here and the await_resume must return the value and not =
a rv-ref to it?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(=
204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><di=
v></div><div><strong>On final_suspend</strong></div><div><br></div><div>I a=
m afraid I cannot answer that without pasting here what I've written in=
P0054. If one of the steps described in P0054 is unclear. Ask me, why Y fo=
llows from X. Otherwise, I am not sure how I can help.</div></div></blockqu=
ote><div><br></div><div>It was pasted in my reply to Nicol Bolas, here it i=
s again:</div><div><br>What is the difference between this:<br>```c++<br>au=
to final_suspend()<br>{<br>=C2=A0 =C2=A0 struct awaiter<br>=C2=A0 =C2=A0 {<=
br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 promise_type * me;<br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 bool await_ready() { return false; }<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
void await_resume() {}<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool await_suspend(co=
routine_handle<>) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto=
need_suspending =3D (me->decrement_refcount() > 0);<br>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return need_suspending;<br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 }<br>=C2=A0 =C2=A0 };<br>=C2=A0 =C2=A0 return awaiter{this};<br>=
}<br>```<br>and this:<br>```c++<br>bool final_suspend()<br>{<br>=C2=A0 =C2=
=A0 auto need_suspending =3D (decrement_refcount() > 0);<br>=C2=A0 =C2=
=A0 return need_suspending;<br>}<br>```<br><br>? In my understanding, it on=
ly matters if `await_suspend` tends to execute the continuation before it r=
eturns, but in the example, it's not the case, I don't see why maki=
ng the coroutine resumable matters before calling `await_suspend` here.<br>=
</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bd74b823278470521cdc4df--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Sun, 11 Oct 2015 14:25:27 +0800
Raw View
--001a1134bce257f3170521ce47e4
Content-Type: text/plain; charset=UTF-8
2015-10-11 6:03 GMT+08:00 Nicol Bolas <jmckesson@gmail.com>:
>
> I'm aware of that. I understand that, somewhere in some library code,
> movement took place. `std::move` was called.
>
> My point is that this is *not apparent to the user*. They don't know it
> happened without looking it up in documentation.
>
And my point is "the user doesn't need to know". Typically the user doesn't
even know there's a coroutine behind the scene, he just see the
coroutine-return-type. The case that the return-type is the `coroutine` is
the exception. An end-user typically doesn't deal with the coroutine
directly.
> In normal code, if you want to move something, the person who currently
> own it must agree to the move, typically by using `std::move`. If you have
> a sequence of functions that all take `unique_ptr`, each and every one of
> them must std::move their value into each function call. Thus making it
> clear that ownership is being transferred at each call site.
>
> We agree that the function who called the coroutine owns it immediately
> after this call. And you want the function who owns the coroutine to lose
> ownership of it, simply by having resumed it.
>
> That is not a transferal of ownership. In a transfer of ownership, the
> source and destination both agree that the source is losing ownership and
> the destination is gaining it.
>
> What you want to do is not *give* ownership; you want to *steal* it. You
> had the coroutine arbitrarily decide that the caller no longer has the
> right to call it. This code cannot be statically inspected to know that
> this has happened, not without the coroutine function's implementation.
>
> I would consider this to be *perfidy*; code willfully lying to other code.
>
It's not lying, it the protocol between the caller and callee - the caller
says to the callee "take me if you want to execute the continuation", and
the callee can make its decision to take it or leave it as is.
> If ownership means "right to call", and the caller of the coroutine had
>>> that right, why should that right be lost without the caller *knowing*
>>> about it? What you seem to want is conceptually no different from this:
>>>
>>> unique_ptr<T> t = make_unique<T>(...);
>>> t->TransferOwnership();
>>> //t is now empty... somehow.
>>>
>>> This doesn't work with smart pointers. And I don't know why you want it
>>> to work with coroutines. Either way, it seems excessively dangerous.
>>>
>>
>> It's more like this: `t->TransferOwnership(t);`
>>
>
> No, that's different. Because you gave it a unique_ptr as an explicit
> parameter, there is at least the possibility of a transfer of ownership.
> Unlike the `coro` case, where there is no apparent reason for `coro` to
> become empty. I'm not saying you couldn't implement it that way; I'm saying
> that it's not *apparent* and is therefore not good code.
>
```c++
template<class T>
void TransferOwnership(unique_ptr<T>& t)
{
t->TransferOwnership(t);
}
```
It's strange to me that you think `TransferOwnership(t)` is different from
`t->TransferOwnership(t)`.
> Also, you missed the `std::move`. Unless you're moving from a reference,
> which is a bad idea, as previously discussed (and hopefully will become a
> core guideline <https://github.com/isocpp/CppCoreGuidelines/issues/316>).
>
In my case, it may or may not be moved, depending on the awaiter.
--
---
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/.
--001a1134bce257f3170521ce47e4
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-11 6:03 GMT+08:00 Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:j=
mckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>:<b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-le=
ft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pad=
ding-left:1ex"><div>I'm aware of that. I understand that, somewhere in =
some library code, movement took place. `std::move` was called.<br><br>My p=
oint is that this is <i>not apparent to the user</i>. They don't know i=
t happened without looking it up in documentation.<br></div></blockquote><d=
iv><br></div><div>And my point is "the user doesn't need to know&q=
uot;. Typically the user doesn't even know there's a coroutine behi=
nd the scene, he just see the coroutine-return-type. The case that the retu=
rn-type is the `coroutine` is the exception. An end-user typically doesn=
9;t deal with the coroutine directly.</div><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;=
border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex=
"><div>In normal code, if you want to move something, the person who curren=
tly own it must agree to the move, typically by using `std::move`. If you h=
ave a sequence of functions that all take `unique_ptr`, each and every one =
of them must std::move their value into each function call. Thus making it =
clear that ownership is being transferred at each call site.<br><br>We agre=
e that the function who called the coroutine owns it immediately after this=
call. And you want the function who owns the coroutine to lose ownership o=
f it, simply by having resumed it.<br><br>That is not a transferal of owner=
ship. In a transfer of ownership, the source and destination both agree tha=
t the source is losing ownership and the destination is gaining it.<br><br>=
What you want to do is not <i>give</i> ownership; you want to <i>steal</i> =
it. You had the coroutine arbitrarily decide that the caller no longer has =
the right to call it. This code cannot be statically inspected to know that=
this has happened, not without the coroutine function's implementation=
..<br><br>I would consider this to be <i>perfidy</i>; code willfully lying t=
o other code.<br></div></blockquote><div><br></div><div>It's not lying,=
it the protocol between the caller and callee - the caller says to the cal=
lee "take me if you want to execute the continuation", and the ca=
llee can make=C2=A0its decision to take it or leave it as is.</div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8e=
x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl=
e:solid;padding-left:1ex"><span class=3D""><blockquote class=3D"gmail_quote=
" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color=
:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr=
"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><div>If ownership mean=
s "right to call", and the caller of the coroutine had that right=
, why should that right be lost without the caller <i>knowing</i> about it?=
What you seem to want is conceptually no different from this:<br><br><div =
style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background-=
color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,0)">unique_=
ptr</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"co=
lor:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">></span><sp=
an style=3D"color:rgb(0,0,0)"> t </span><span style=3D"color:rgb(102,102,0)=
">=3D</span><span style=3D"color:rgb(0,0,0)"> make_unique</span><span style=
=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</sp=
an><span style=3D"color:rgb(102,102,0)">>(...);</span><span style=3D"col=
or:rgb(0,0,0)"><br>t</span><span style=3D"color:rgb(102,102,0)">-></span=
><span style=3D"color:rgb(102,0,102)">TransferOwnership</span><span style=
=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(136,0,0)">//t is now empty... somehow.</span>=
</div></code></div><br>This doesn't work with smart pointers. And I don=
't know why you want it to work with coroutines. Either way, it seems e=
xcessively dangerous.<br></div></blockquote><div><br></div><div>It's mo=
re like this: `t->TransferOwnership(t);`</div></div></div></div></blockq=
uote></span><div><br>No, that's different. Because you gave it a unique=
_ptr as an explicit parameter, there is at least the possibility of a trans=
fer of ownership. Unlike the `coro` case, where there is no apparent reason=
for `coro` to become empty. I'm not saying you couldn't implement =
it that way; I'm saying that it's not <i>apparent</i> and is theref=
ore not good code.</div></blockquote><div><br></div>```c++<br>template<c=
lass T><br>void TransferOwnership(unique_ptr<T>& t)<br>{<br>=
=C2=A0 =C2=A0 t->TransferOwnership(t);<br>}<br>```</div><div class=3D"gm=
ail_quote"><br></div><div class=3D"gmail_quote">It's strange to me that=
you think `TransferOwnership(t)` is=C2=A0different from `t->TransferOwn=
ership(t)`.</div><div class=3D"gmail_quote"><div>=C2=A0</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px=
;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1e=
x"><div>Also, you missed the `std::move`. Unless you're moving from a r=
eference, which is a bad idea, as previously discussed (and hopefully will =
<a href=3D"https://github.com/isocpp/CppCoreGuidelines/issues/316" target=
=3D"_blank">become a core guideline</a>).<br></div></blockquote><div><br></=
div><div>In my case, it may or may not be moved, depending on the awaiter.<=
/div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134bce257f3170521ce47e4--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 06:17:41 -0700 (PDT)
Raw View
------=_Part_1183_436627790.1444569461477
Content-Type: multipart/alternative;
boundary="----=_Part_1184_837615224.1444569461478"
------=_Part_1184_837615224.1444569461478
Content-Type: text/plain; charset=UTF-8
Hi Tongari:
I do not understand how decision whether coroutine_handle<> has RAII
semantic or not has any bearing on the example you shown.
The behavior of
std::future<void> f() {
Resource res(...);
await std::suspend_always{};
}
depends solely on what semantics of the future and suspend_always is.
If future returned here has RAII semantics, like the future produced by
std::async, then we will have deadlock as the future destructor will block
forever in its destructor. If future has "leak async" semantic like the
future returned from promise.get_future(), it will result in a leak. In
C++17 or later, I would like to have a better vocabulary type that supports
cancellation, let's call it STLv2 future, in that case, it will cancel the
coroutine in its destructor, thus avoiding the leak.
suspend_always have the semantics implied by its name. Unconditional
suspend at this point. If customer requested this, coroutine will suspend.
Period. If you disagree with semantics of suspend_always or would like it
to have more obscure name that is fine. Also, I consider suspend_always to
be a library class. It is not special in any way form compiler perspective.
I included it in the proposal, because it is something that I felt people
will be writing themselves anyways, so putting it in the standard library
will allow to avoid the repetition and give some common vocabulary name.
(It may be not the best name, I am open to suggestions. Earlier it was
suspend_now).
In both cases, we discuss what semantics a library writer wants to impart
to the future and suspend_always. That behavior is what library writer
designs. How coroutine_handle behaves has no bearing on that decision.
*On future evolution*
There reason I added the section about it in P0054 was to show that such
exploration is possible in the future. It should not stop progress on this
proposal.
>
> What if the future exploration is not compatible with the current design?
> that's my concern.
>
I think both the "automatically awaited awaitables" idea of P0054 and your
idea about async mofified on a function are compatible and can be built on
top of P0057.
*On awaitable return_value*
>
>> I store a reference to the expression (lvalue or temporary on the
>> coroutine frame) and give a chance to consumer, potentially running on a
>> different thread to observe it before semicolon at the end of full
>> expression destroys the value (or leaving the scope and stopping at final
>> suspend destroys the lvalue that I was trying to return)
>>
>
> I kinda get the idea, but how can the consumer notify the promise that it
> takes the value?
>
Consumer will resume the coroutine when it is consumed the value.
*On final_suspend*
> What is the difference between this:
>> ```c++
>> auto final_suspend()
>> {
>> struct awaiter
>> {
>> promise_type * me;
>> bool await_ready() { return false; }
>> void await_resume() {}
>> bool await_suspend(coroutine_handle<>) {
>> auto need_suspending = (me->decrement_refcount() > 0);
>> return need_suspending;
>> }
>> };
>> return awaiter{this};
>> }
>> ```
>> and this:
>> ```c++
>> bool final_suspend()
>> {
>> auto need_suspending = (decrement_refcount() > 0); ((<-- HERE))
>> return need_suspending;
>> }
>> ```
>>
>
Just like with initial_suspend, you need to think where PrepareForSuspend
goes relative to a call to final_suspend.
Note, that as soon as you do (decrement_refcount() > 0), a racing thread
that has an owning handle to a coroutine will decrement the refcount,
observe that it is zero now and destroys the coroutine while the current
thread is still at the semicolon marked with HERE tag in the example above.
Thus, just like with initial_suspend we explore the cases:
Option 1: (Busted, due to the race described above and in P0054)
if (final_suspend()) {
PrepareForSuspend();
DoSuspend();
}
Option 2: (Works but suboptimal, since now we do prepare for suspend even
when we never suspend)
PrepareForSuspend();
if (final_suspend()) {
DoSuspend();
}
Option 3:
if (is_final_suspend_means_to_suspend()) {
PrepareForSuspend();
if (final_suspend()) {
DoSuspend();
}
}
or in a simpler form
await final_suspend()
--
---
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_1184_837615224.1444569461478
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi Tongari:</div><div><br></div><div>I do not underst=
and how decision whether coroutine_handle<> has RAII semantic or not =
has any bearing on the example you shown.</div><div>The behavior of</div><d=
iv><br></div><div><p><font face=3D"Consolas" size=3D"2"><font face=3D"Conso=
las" size=3D"2">std::future<</font></font><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"=
2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">void</font></font><=
/font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"=
>> f() {</font></font></p><font face=3D"Consolas" size=3D"2"><font face=
=3D"Consolas" size=3D"2">
<p> =C2=A0=C2=A0 Resource res(...);</p>
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0 await</font></font></fon=
t><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> st=
d::suspend_always{};</font></font></p><font face=3D"Consolas" size=3D"2"><f=
ont face=3D"Consolas" size=3D"2">
<p>}</p></font></font></div><div><br></div><div>depends solely on what sema=
ntics of the future and suspend_always is.</div><div><br></div><div>If futu=
re returned here has RAII semantics, like the future produced by std::async=
, then we will have deadlock as the=C2=A0future destructor=C2=A0will block =
forever in its destructor. If future has "leak async" semantic li=
ke the future returned from promise.get_future(), it will result in a leak.=
In C++17 or later, I would like to have a better vocabulary type that supp=
orts cancellation, let's call it STLv2 future, in that case, it will ca=
ncel the coroutine in its destructor, thus avoiding the leak.</div><div><br=
></div><div>suspend_always have the semantics implied by its name. Uncondit=
ional suspend at this point. If customer requested this, coroutine will sus=
pend. Period. If you disagree with semantics of suspend_always or would lik=
e it to have more obscure name that is fine. Also, I consider suspend_alway=
s to be a library class. It is not special in any way form compiler perspec=
tive. I included it in the proposal, because it is something that I felt pe=
ople will be writing themselves anyways, so putting it in the standard libr=
ary will allow to avoid the repetition and give some common vocabulary name=
.. (It may be not the best name, I am open to suggestions. Earlier it was su=
spend_now).</div><div><br></div><div>In both cases, we discuss what semanti=
cs a library writer wants to impart to the future and suspend_always. That =
behavior is what library writer designs. How coroutine_handle behaves has n=
o bearing on that decision.</div><div><br></div><div><strong>On future evol=
ution</strong></div><div><br>There reason=C2=A0I added the section about it=
in P0054 was to show that such exploration is possible in the future. It s=
hould not stop progress on this proposal.</div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-co=
lor: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"=
><div dir=3D"ltr"><div><div class=3D"gmail_quote"><div><br></div><div>What =
if the future exploration is not compatible with the current design? that&#=
39;s my concern.</div></div></div></div></blockquote><div><br></div><div>I=
=C2=A0think both the "automatically awaited awaitables" idea of P=
0054 and your idea about async mofified on a function are compatible and ca=
n be built on top of P0057.=C2=A0<br>=C2=A0</div><div><strong>On awaitable =
return_value</strong></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 2=
04); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><d=
iv><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204=
, 204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"=
><div><br></div><div>I store=C2=A0a reference to the expression (lvalue or =
temporary on the coroutine frame) and give a chance to consumer, potentiall=
y running on a different thread to observe it before semicolon at the end o=
f full expression destroys the value (or leaving the scope and stopping at =
final suspend destroys the lvalue that I was trying to return)</div></div><=
/blockquote><div><br></div><div>I kinda get the idea, but how can the consu=
mer notify the promise that it takes the value?<br></div></div></div></div>=
</blockquote><div><br></div><div>Consumer will=C2=A0resume the coroutine wh=
en it is consumed the value. </div><div>=C2=A0</div><div><strong>On final_s=
uspend</strong></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(=
204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" =
style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: r=
gb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div =
dir=3D"ltr"><div>What is the difference between this:<br>```c++<br>auto fin=
al_suspend()<br>{<br>=C2=A0 =C2=A0 struct awaiter<br>=C2=A0 =C2=A0 {<br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 promise_type * me;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
bool await_ready() { return false; }<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 void aw=
ait_resume() {}<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool await_suspend(coroutine=
_<wbr>handle<>) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto n=
eed_suspending =3D (me->decrement_refcount() > 0);<br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return need_suspending;<br>=C2=A0 =C2=A0 =C2=A0=
=C2=A0 }<br>=C2=A0 =C2=A0 };<br>=C2=A0 =C2=A0 return awaiter{this};<br>}<b=
r>```<br>and this:<br>```c++<br>bool final_suspend()<br>{<br>=C2=A0 =C2=A0 =
auto need_suspending =3D (decrement_refcount() > 0); ((<-- HERE))<br>=
=C2=A0=C2=A0=C2=A0 return need_suspending;<br>}<br>```<br></div></div></blo=
ckquote></div></div></div></blockquote><div><br></div><div>=C2=A0Just like =
with initial_suspend, you need to think where PrepareForSuspend goes relati=
ve to a call to final_suspend.</div><div>Note, that as soon as you do (decr=
ement_refcount() > 0), a racing thread that has an owning handle to a co=
routine will decrement the refcount, observe that it is zero now and destro=
ys the coroutine while the current thread is still at the semicolon marked =
with HERE tag in the example above.</div><div><br></div><div>Thus, just lik=
e with initial_suspend we explore the cases:</div><div><br></div><div>Optio=
n 1: (Busted, due to the race described above and in P0054)</div><div><br><=
/div><div>if (final_suspend()) {</div><div>=C2=A0=C2=A0 PrepareForSuspend()=
;</div><div>=C2=A0=C2=A0 DoSuspend();</div><div>}</div><div><br></div><div>=
Option 2: (Works but suboptimal, since now we do prepare for suspend even w=
hen we never suspend)</div><div><br></div><div><div><div>PrepareForSuspend(=
);</div>if (final_suspend()) {</div><div>=C2=A0=C2=A0 DoSuspend();</div><di=
v>}</div><div><br></div><div>Option 3:</div><div><br></div><div>if (is_fina=
l_suspend_means_to_suspend()) {</div><div><div><div>=C2=A0 PrepareForSuspen=
d();</div>=C2=A0 if (final_suspend()) {</div><div>=C2=A0=C2=A0=C2=A0 =C2=A0=
DoSuspend();</div><div>=C2=A0 }</div><div>}</div><div><br></div><div>or in =
a simpler form</div><div><br></div><div>await final_suspend()</div></div></=
div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1184_837615224.1444569461478--
------=_Part_1183_436627790.1444569461477--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 06:28:21 -0700 (PDT)
Raw View
------=_Part_4556_367978680.1444570101395
Content-Type: multipart/alternative;
boundary="----=_Part_4557_677220156.1444570101395"
------=_Part_4557_677220156.1444570101395
Content-Type: text/plain; charset=UTF-8
Quick typo fixes:
.... your idea about async *mofified* on a function (though I really like
the word mofified, I meant *modifier).*
And also I want to inject myself into your subthread with Nicol and repeat
what I stated before.
Semantic of the examples you have shown to Nicol, should be based on what
is the designed behavior for those primitives.
You can achieve the designed behavior irrespectively of whether
coroutine_handle behaves like prescribed by P0057 or has the semantics you
desire.
coroutine_handle is a low level facility to build higher level constructs
from it.
You design what behavior you want high-level construct to have.
coroutine_handle is there so that your design can be implemented in most
efficient way
--
---
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_4557_677220156.1444570101395
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Quick typo fixes:</div><div><br></div><div>... your i=
dea about async <strong>mofified</strong> on a function=C2=A0 (though I rea=
lly like the word mofified, I meant <strong>modifier).</strong></div><div><=
strong><br></strong></div><div>And also I want to inject myself into your s=
ubthread with Nicol and repeat what I stated before.</div><div><br></div><d=
iv>Semantic of the examples you have shown to Nicol, should be based on wha=
t is the designed behavior for those primitives. </div><div>You can achieve=
the designed behavior irrespectively of whether coroutine_handle behaves l=
ike prescribed by P0057 or has the semantics you desire.</div><div>coroutin=
e_handle is a low level facility to build higher level constructs from it. =
</div><div><br></div><div>You design what behavior you want high-level cons=
truct to have. coroutine_handle is there so that your design can be impleme=
nted in most efficient way</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4557_677220156.1444570101395--
------=_Part_4556_367978680.1444570101395--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 06:39:20 -0700 (PDT)
Raw View
------=_Part_3690_454692222.1444570760853
Content-Type: multipart/alternative;
boundary="----=_Part_3691_2112941385.1444570760853"
------=_Part_3691_2112941385.1444570760853
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 1:48:50 AM UTC-4, TONGARI J wrote:
>
> Hi Gor,
>
> 2015-10-11 4:37 GMT+08:00 Gor Nishanov <gorni...@gmail.com <javascript:>>:
>
>> Moreover, we gave the higher-level semantics to the coroutine_handle. If
>> that does not match what the library wants to do, it now needs to add code
>> to suppress that behavior, (for example if it does not want ownership
>> semantic, it should zero out the handle before the destruction).
>>
>> coroutine_handle is not for the end user. It is a sharp tool for the
>> library writer. Moreover it is a compiler provided tool. If I don't like
>> the library, I can write my own. If I don't like what compiler gives me, I
>> am not going to write a new compiler.
>>
>> Currently, it is a raw pointer. You cannot get any more efficient than
>> that. It is fully devoid of higher level semantics. As a library writer you
>> decide what it means. You decide what trade-offs to do and what efficiency
>> you want to sacrifice for ease of use. I as a compiler don't want to make
>> any trade-offs. I give pretty syntactic sugar to the end-user and a bunch
>> of sharp knives to the library developer.
>>
>> I am open to any suggestions how to make the library adaptation layers
>> more library writer friendly as long as I don't have to sacrifice
>> performance in space or time.
>>
>
> Bear in mind that the coroutine-promises and the awaitables could be
> written by different people in different libraries, there must exist a
> protocol for them to collaborate safely without knowing each other.
> Something like "generator" is really a special case, where the promise also
> controls the awaitable (i.e. yield_value). For other async-result, we need
> the safe semantic anyway.
>
> Consider my earlier example:
>
> ```c++
> std::future<void> f()
> {
> Resource res(...);
> await std::suspend_always{};
> }
> ```
>
> Do you really think that it's better to have f() leak memory & resource by
> default? I don't think so.
>
I'm not exactly sure how this constitutes a memory leak.
If coroutine_traits uses the default case for `f`, then it will attempt to
create `future<void>::promise_type` for the coroutine promise. So either
`future` has been updated to have such a promise, or it has not.
If it has not, then this is a compiler error. If it has, then it's up to
the promise type to ultimately destroy the coroutine_handle. And therefore,
there would only be a memory leak if `future<void>::promise_type` was
*broken*.
The analogy Gor and I have been using with pointers is apt. A pointer has
no ownership semantics; you have to manually manage memory for them. But a
smart pointer does; that's why we use them. `coroutine_handle` has no
ownership semantics. But the `promise_type` *does*.
Just as RAII lives in `unique_ptr<T>` rather than T*, RAII lives at the
level of the promise rather than `coroutine_handle`.
And that's not a contrived example, I do do things like that for
> cascading-cancellation of tasks in dependency-graph.
> With RAII, the cancellation in one node propagates to its dependants
> automatically, without exceptions.
> Without RAII, to provide the similar behavior, you have to throw exception
> that will be catch by its dependants and then throw it again and catch that
> in the dependants-of-dependants and so on...which is less performant.
>
>
>> *On keywords:*
>>
>> It is not about keywords, correct? P0071 offers a magic std::await and
>> std::yield functions as an alternative.
>> Your concern is with design point that P0054 requires that every suspend
>> point in a function needs to be explicitly marked whether with a keyword or
>> magic function.
>>
>> I have no objections to exploring whether in the future we may get
>> "automatically awaited awaitables" or async functions as you suggested in
>> your proposal on the github. Sure thing. Go right ahead. Should we wait and
>> not standardize coroutines while this exploration is going on?
>>
>> There reason I added the section about it in P0054 was to show that such
>> exploration is possible in the future. It should not stop progress on this
>> proposal.
>>
>
> What if the future exploration is not compatible with the current design?
> that's my concern.
>
And what if future exploration of adding template implementation checks to
concepts is not compatible with the current function-based design of the
concepts TS? That certainly didn't stop them from writing that up.
We should not arrest important developments because we're afraid that some
functionality *might* not work out in the future (especially if its
functionality we aren't sure we necessarily want). We should certainly look
at such possibilities, but so long as they seem feasible to implement, we
don't need to make absolutely sure before moving forward.
I understand your concern here, but vague "what ifs" should not be used to
derail a proposal. We need coroutines in the language, ASAP. And this
proposal is a mature, well-founded concept (based on similar behavior in
many other languages) with solid implementation and optimization experience.
If you want to argue that the current design is not compatible with
implicit awaiting, then I feel the burden of proof is on you. You should
provide evidence of that, not vague concerns about what may or may not
happen.
--
---
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_3691_2112941385.1444570760853
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Sunday, October 11, 2015 at 1:48:50 AM UTC-4, TONGARI J wrote:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">Hi Gor,<br><div=
><br><div class=3D"gmail_quote">2015-10-11 4:37 GMT+08:00 Gor Nishanov <spa=
n dir=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-=
mailto=3D"x_LaGJyQDQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'ja=
vascript:';return true;" onclick=3D"this.href=3D'javascript:';r=
eturn true;">gorni...@gmail.com</a>></span>:<br><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1p=
x;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1=
ex"><div dir=3D"ltr"><div>Moreover, we gave the higher-level semantics to t=
he coroutine_handle. If that does not match what the library wants to do,=
=C2=A0it=C2=A0now needs to add code to suppress that behavior, (for example=
if=C2=A0it does not want ownership semantic,=C2=A0it should zero out the h=
andle before the destruction).</div><div><br></div><div>coroutine_handle is=
not for the end user. It is a sharp tool for the library writer. Moreover =
it is a compiler provided tool. If I don't like the library, I can writ=
e my own. If I don't like what compiler gives me, I am not going to wri=
te a new compiler.</div><div><br></div><div>Currently, it is a raw pointer.=
You cannot get any more efficient than that. It is fully devoid of higher =
level semantics. As a library writer you decide what it means. You decide w=
hat trade-offs to do and what efficiency you want to sacrifice for ease of =
use. I as a compiler don't want to make any trade-offs. I give pretty s=
yntactic sugar to the end-user and=C2=A0a bunch of sharp knives to the libr=
ary developer.</div><div><br></div><div>I am open to any suggestions how to=
make the library adaptation layers more library writer friendly as long as=
I don't have to sacrifice performance in space or time.</div></div></b=
lockquote><div><br></div><div>Bear in mind that the coroutine-promises and =
the awaitables could be written by different people in different libraries,=
there must exist a protocol for them to collaborate safely without knowing=
each other. Something like "generator" is=C2=A0really=C2=A0a spe=
cial case, where the promise also controls the awaitable (i.e. yield_value)=
.. For other async-result, we need the safe semantic anyway.</div><div><br><=
/div><div>Consider my earlier example:</div><div><br></div><div>```c++</div=
>std::future<void> f()</div><div class=3D"gmail_quote">{</div><div cl=
ass=3D"gmail_quote">=C2=A0 =C2=A0 Resource res(...);</div><div class=3D"gma=
il_quote">=C2=A0 =C2=A0=C2=A0await std::suspend_always{};</div><div class=
=3D"gmail_quote">}</div><div class=3D"gmail_quote">```</div><div class=3D"g=
mail_quote"><br></div><div class=3D"gmail_quote">Do you really think that i=
t's better to have f() leak memory & resource by default? I don'=
;t think so.</div></div></div></blockquote><div><br>I'm not exactly sur=
e how this constitutes a memory leak.<br><br>If coroutine_traits uses the d=
efault case for `f`, then it will attempt to create `future<void>::pr=
omise_type` for the coroutine promise. So either `future` has been updated =
to have such a promise, or it has not.<br><br>If it has not, then this is a=
compiler error. If it has, then it's up to the promise type to ultimat=
ely destroy the coroutine_handle. And therefore, there would only be a memo=
ry leak if `future<void>::promise_type` was <i>broken</i>.<br><br>The=
analogy Gor and I have been using with pointers is apt. A pointer has no o=
wnership semantics; you have to manually manage memory for them. But a smar=
t pointer does; that's why we use them. `coroutine_handle` has no owner=
ship semantics. But the `promise_type` <i>does</i>.<br><br>Just as RAII liv=
es in `unique_ptr<T>` rather than T*, RAII lives at the level of the =
promise rather than `coroutine_handle`.<br><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quote">And=
that's not a contrived example, I do do things like that for cascading=
-cancellation of tasks in dependency-graph.</div><div class=3D"gmail_quote"=
>With RAII, the cancellation in one node propagates to its dependants autom=
atically, without exceptions.</div><div class=3D"gmail_quote">Without RAII,=
to provide the similar behavior, you have to throw exception that will be =
catch by its dependants and then throw it again and catch that in the=C2=A0=
dependants-of-dependants and so on...which is less performant.</div><div cl=
ass=3D"gmail_quote"><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div=
></div><div><b>On keywords:</b></div><div><br></div><div>It is not about ke=
ywords, correct? P0071 offers a magic std::await and std::yield functions a=
s an alternative.</div><div>Your concern is with design point that P0054 re=
quires that every suspend point in=C2=A0a function needs to be explicitly m=
arked whether with a keyword or magic function. </div><div><br></div><div>I=
have no objections=C2=A0to exploring whether in the future we may get &quo=
t;automatically awaited awaitables" or async functions as you suggeste=
d in your proposal on the github. Sure thing. Go right ahead. Should we wai=
t and not standardize coroutines while this exploration is going on?<br><br=
>There reason=C2=A0I added the section about it in P0054 was to show that s=
uch exploration is possible in the future. It should not stop progress on t=
his proposal.</div></div></blockquote><div><br></div><div>What if the futur=
e exploration is not compatible with the current design? that's my conc=
ern.</div></div></div></div></blockquote><div><br></div>And what if future =
exploration of adding template implementation checks to concepts is not com=
patible with the current function-based design of the concepts TS? That cer=
tainly didn't stop them from writing that up.<br><br>We should not arre=
st important developments because we're afraid that some functionality =
<i>might</i> not work out in the future (especially if its functionality we=
aren't sure we necessarily want). We should certainly look at such pos=
sibilities, but so long as they seem feasible to implement, we don't ne=
ed to make absolutely sure before moving forward.<br><br>I understand your =
concern here, but vague "what ifs" should not be used to derail a=
proposal. We need coroutines in the language, ASAP. And this proposal is a=
mature, well-founded concept (based on similar behavior in many other lang=
uages) with solid implementation and optimization experience.<br><br>If you=
want to argue that the current design is not compatible with implicit awai=
ting, then I feel the burden of proof is on you. You should provide evidenc=
e of that, not vague concerns about what may or may not happen.<br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3691_2112941385.1444570760853--
------=_Part_3690_454692222.1444570760853--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 07:38:16 -0700 (PDT)
Raw View
------=_Part_215_438267221.1444574296602
Content-Type: multipart/alternative;
boundary="----=_Part_216_113176294.1444574296602"
------=_Part_216_113176294.1444574296602
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 2:25:29 AM UTC-4, TONGARI J wrote:
>
> 2015-10-11 6:03 GMT+08:00 Nicol Bolas <jmck...@gmail.com <javascript:>>:
>>
>> I'm aware of that. I understand that, somewhere in some library code,
>> movement took place. `std::move` was called.
>>
>> My point is that this is *not apparent to the user*. They don't know it
>> happened without looking it up in documentation.
>>
>
> And my point is "the user doesn't need to know". Typically the user
> doesn't even know there's a coroutine behind the scene, he just see the
> coroutine-return-type.
>
Define "typically".
If you're executing an asynchronous process, you usually need to know that
it's asynchronous. The caller needs to make a decision about how to
interact with this "coroutine-return-type", since the whole point of an
async process is that it's not necessarily available yet. If it's not
available, does he wait for it to finish, blocking the current execution?
Does he `await` for it to become available (thus putting the burden on his
caller)? Or does he poll an object to see if the value is available, doing
other processing in the meantime if it isn't?
Even resumable expressions don't make these decisions transparent.
The case that the return-type is the `coroutine` is the exception. An
> end-user typically doesn't deal with the coroutine directly.
>
The point of a coroutine is that it can stop execution and be resumed
later. A function is made a coroutine for one of two reasons (which can be
combined):
1) The function will repeatedly return values, transferring control to its
caller between them.
2) The function will not be able to actually return its value immediately
(or otherwise signal that it's finished its task).
Neither of these is something that the function directly invoking the
coroutine can completely ignore.
You can devise a special return value object that hides these details. But
even then, it's clear to the user that they're playing with something
special, not a normal function call. So I don't buy the idea that the user
can be entirely ignorant of a given function being a coroutine.
In normal code, if you want to move something, the person who currently own
>> it must agree to the move, typically by using `std::move`. If you have a
>> sequence of functions that all take `unique_ptr`, each and every one of
>> them must std::move their value into each function call. Thus making it
>> clear that ownership is being transferred at each call site.
>>
>> We agree that the function who called the coroutine owns it immediately
>> after this call. And you want the function who owns the coroutine to lose
>> ownership of it, simply by having resumed it.
>>
>> That is not a transferal of ownership. In a transfer of ownership, the
>> source and destination both agree that the source is losing ownership and
>> the destination is gaining it.
>>
>> What you want to do is not *give* ownership; you want to *steal* it. You
>> had the coroutine arbitrarily decide that the caller no longer has the
>> right to call it. This code cannot be statically inspected to know that
>> this has happened, not without the coroutine function's implementation.
>>
>> I would consider this to be *perfidy*; code willfully lying to other
>> code.
>>
>
> It's not lying, it the protocol between the caller and callee - the caller
> says to the callee "take me if you want to execute the continuation", and
> the callee can make its decision to take it or leave it as is.
>
Then we're going to have to agree to disagree about that, because I don't
believe that ownership of anything should be transferred without consent.
*Explicit* consent. If the caller ever owned that coroutine, then it's on
the caller to transfer that ownership elsewhere.
That being said, I don't believe there is anything in the current design
which actively *prevents* you from creating a promise type/awaitable that
behaves this way. If you want to implement such a transfer of ownership,
the design does not prevent you from doing so.
> If ownership means "right to call", and the caller of the coroutine had
>>>> that right, why should that right be lost without the caller *knowing*
>>>> about it? What you seem to want is conceptually no different from this:
>>>>
>>>> unique_ptr<T> t = make_unique<T>(...);
>>>> t->TransferOwnership();
>>>> //t is now empty... somehow.
>>>>
>>>> This doesn't work with smart pointers. And I don't know why you want it
>>>> to work with coroutines. Either way, it seems excessively dangerous.
>>>>
>>>
>>> It's more like this: `t->TransferOwnership(t);`
>>>
>>
>> No, that's different. Because you gave it a unique_ptr as an explicit
>> parameter, there is at least the possibility of a transfer of ownership.
>> Unlike the `coro` case, where there is no apparent reason for `coro` to
>> become empty. I'm not saying you couldn't implement it that way; I'm saying
>> that it's not *apparent* and is therefore not good code.
>>
>
> ```c++
> template<class T>
> void TransferOwnership(unique_ptr<T>& t)
> {
> t->TransferOwnership(t);
> }
> ```
>
> It's strange to me that you think `TransferOwnership(t)` is different from
> `t->TransferOwnership(t)`.
>
I didn't say it was. I said that `t->TransferOwnership(t)` is different
from `t->TransferOwnership()`, which was what you first proposed. In one
case, you pass the owning object as a parameter. In the other case, you
snatch ownership via... well, means that are impossible in C++.
--
---
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_216_113176294.1444574296602
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sunday, October 11, 2015 at 2:25:29 AM UTC-4, TONGARI J wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmai=
l_quote">2015-10-11 6:03 GMT+08:00 Nicol Bolas <span dir=3D"ltr"><<a hre=
f=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"j61PHJySDQAJ" =
rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';return tr=
ue;" onclick=3D"this.href=3D'javascript:';return true;">jmck...@gma=
il.com</a>></span>:<blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex"><div>I'm aware of that. I unders=
tand that, somewhere in some library code, movement took place. `std::move`=
was called.<br><br>My point is that this is <i>not apparent to the user</i=
>. They don't know it happened without looking it up in documentation.<=
br></div></blockquote><div><br></div><div>And my point is "the user do=
esn't need to know". Typically the user doesn't even know ther=
e's a coroutine behind the scene, he just see the coroutine-return-type=
..</div></div></div></div></blockquote><div><br>Define "typically"=
..<br><br>If you're executing an asynchronous process, you usually need =
to know that it's asynchronous. The caller needs to make a decision abo=
ut how to interact with this "coroutine-return-type", since the w=
hole point of an async process is that it's not necessarily available y=
et. If it's not available, does he wait for it to finish, blocking the =
current execution? Does he `await` for it to become available (thus putting=
the burden on his caller)? Or does he poll an object to see if the value i=
s available, doing other processing in the meantime if it isn't?<br><br=
>Even resumable expressions don't make these decisions transparent.<br>=
<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v><div class=3D"gmail_quote"><div>The case that the return-type is the `cor=
outine` is the exception. An end-user typically doesn't deal with the c=
oroutine directly.</div></div></div></div></blockquote><div><br>The point o=
f a coroutine is that it can stop execution and be resumed later. A functio=
n is made a coroutine for one of two reasons (which can be combined):<br><b=
r>1) The function will repeatedly return values, transferring control to it=
s caller between them.<br><br>2) The function will not be able to actually =
return its value immediately (or otherwise signal that it's finished it=
s task).<br><br>Neither of these is something that the function directly in=
voking the coroutine can completely ignore.<br><br>You can devise a special=
return value object that hides these details. But even then, it's clea=
r to the user that they're playing with something special, not a normal=
function call. So I don't buy the idea that the user can be entirely i=
gnorant of a given function being a coroutine.<br><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"gmail_quo=
te"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bor=
der-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:sol=
id;padding-left:1ex"><div>In normal code, if you want to move something, th=
e person who currently own it must agree to the move, typically by using `s=
td::move`. If you have a sequence of functions that all take `unique_ptr`, =
each and every one of them must std::move their value into each function ca=
ll. Thus making it clear that ownership is being transferred at each call s=
ite.<br><br>We agree that the function who called the coroutine owns it imm=
ediately after this call. And you want the function who owns the coroutine =
to lose ownership of it, simply by having resumed it.<br><br>That is not a =
transferal of ownership. In a transfer of ownership, the source and destina=
tion both agree that the source is losing ownership and the destination is =
gaining it.<br><br>What you want to do is not <i>give</i> ownership; you wa=
nt to <i>steal</i> it. You had the coroutine arbitrarily decide that the ca=
ller no longer has the right to call it. This code cannot be statically ins=
pected to know that this has happened, not without the coroutine function&#=
39;s implementation.<br><br>I would consider this to be <i>perfidy</i>; cod=
e willfully lying to other code.<br></div></blockquote><div><br></div><div>=
It's not lying, it the protocol between the caller and callee - the cal=
ler says to the callee "take me if you want to execute the continuatio=
n", and the callee can make=C2=A0its decision to take it or leave it a=
s is.</div></div></div></div></blockquote><div><br>Then we're going to =
have to agree to disagree about that, because I=20
don't believe that ownership of anything should be transferred without=
=20
consent. <i>Explicit</i> consent. If the caller ever owned that coroutine, =
then it's on the caller to transfer that ownership elsewhere.<br><br>Th=
at being said, I don't believe there is anything in the current design =
which actively <i>prevents</i> you from creating a promise type/awaitable t=
hat behaves this way. If you want to implement such a transfer of ownership=
, the design does not prevent you from doing so.<br>=C2=A0<br></div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div class=3D"g=
mail_quote"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><span><blockquote class=3D"gmail_qu=
ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co=
lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=3D"=
ltr"><div><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(2=
04,204,204);border-left-style:solid;padding-left:1ex"><div>If ownership mea=
ns "right to call", and the caller of the coroutine had that righ=
t, why should that right be lost without the caller <i>knowing</i> about it=
? What you seem to want is conceptually no different from this:<br><br><div=
style=3D"border:1px solid rgb(187,187,187);word-wrap:break-word;background=
-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,0)">unique=
_ptr</span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"c=
olor:rgb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">></span><s=
pan style=3D"color:rgb(0,0,0)"> t </span><span style=3D"color:rgb(102,102,0=
)">=3D</span><span style=3D"color:rgb(0,0,0)"> make_unique</span><span styl=
e=3D"color:rgb(102,102,0)"><</span><span style=3D"color:rgb(0,0,0)">T</s=
pan><span style=3D"color:rgb(102,102,0)">>(...);</span><span style=3D"co=
lor:rgb(0,0,0)"><br>t</span><span style=3D"color:rgb(102,102,0)">-></spa=
n><span style=3D"color:rgb(102,0,102)">TransferOwnership</span><span style=
=3D"color:rgb(102,102,0)">();</span><span style=3D"color:rgb(0,0,0)"><br></=
span><span style=3D"color:rgb(136,0,0)">//t is now empty... somehow.</span>=
</div></code></div><br>This doesn't work with smart pointers. And I don=
't know why you want it to work with coroutines. Either way, it seems e=
xcessively dangerous.<br></div></blockquote><div><br></div><div>It's mo=
re like this: `t->TransferOwnership(t);`</div></div></div></div></blockq=
uote></span><div><br>No, that's different. Because you gave it a unique=
_ptr as an explicit parameter, there is at least the possibility of a trans=
fer of ownership. Unlike the `coro` case, where there is no apparent reason=
for `coro` to become empty. I'm not saying you couldn't implement =
it that way; I'm saying that it's not <i>apparent</i> and is theref=
ore not good code.</div></blockquote><div><br></div>```c++<br>template<c=
lass T><br>void TransferOwnership(unique_ptr<<wbr>T>& t)<br>{<=
br>=C2=A0 =C2=A0 t->TransferOwnership(t);<br>}<br>```</div><div class=3D=
"gmail_quote"><br></div><div class=3D"gmail_quote">It's strange to me t=
hat you think `TransferOwnership(t)` is=C2=A0different from `t->Transfer=
Ownership(t)`.</div></div></div></blockquote><div><br>I didn't say it w=
as. I said that `t->TransferOwnership(t)` is different from `t->Trans=
ferOwnership()`, which was what you first proposed. In one case, you pass t=
he owning object as a parameter. In the other case, you snatch ownership vi=
a... well, means that are impossible in C++.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_216_113176294.1444574296602--
------=_Part_215_438267221.1444574296602--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 07:51:43 -0700 (PDT)
Raw View
------=_Part_1366_1511276333.1444575103393
Content-Type: multipart/alternative;
boundary="----=_Part_1367_1157515405.1444575103393"
------=_Part_1367_1157515405.1444575103393
Content-Type: text/plain; charset=UTF-8
>
> I didn't say it was. I said that `t->TransferOwnership(t)` is different
> from `t->TransferOwnership()`, which was what you first proposed. In one
> case, you pass the owning object as a parameter. In the other case, you
> snatch ownership via... well, means that are impossible in C++.
>
Nicol, you have too much faith in goodness of the developer. Some of them
could be truly evil and code up the following:
T::TransferOwnership() const {
g_some_var = std::move(*const_cast<T*>(this));
}
Sorry, could not resist :-P
--
---
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_1367_1157515405.1444575103393
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;"><div>I didn't say it was.=
I said that `t->TransferOwnership(t)` is different from `t->Transfer=
Ownership()`, which was what you first proposed. In one case, you pass the =
owning object as a parameter. In the other case, you snatch ownership via..=
.. well, means that are impossible in C++.<br></div></blockquote><div><br></=
div><div>Nicol, you have too much faith in goodness of the developer. Some =
of them could be truly evil and code up the following:</div><div><br></div>=
<div><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"=
2">T::TransferOwnership() </font></font><font color=3D"#0000ff" face=3D"Con=
solas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><fon=
t color=3D"#0000ff" face=3D"Consolas" size=3D"2">const</font></font></font>=
<font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> {</f=
ont></font></p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" s=
ize=3D"2">
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> =C2=A0=C2=A0 g_some_var =3D std::move(*</font></font><font c=
olor=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=
=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"=
2">const_cast</font></font></font><font face=3D"Consolas" size=3D"2"><font =
face=3D"Consolas" size=3D"2"><T*>(</font></font><font color=3D"#0000f=
f" face=3D"Consolas" size=3D"2"><font color=3D"#0000ff" face=3D"Consolas" s=
ize=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2">this</font><=
/font></font><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" siz=
e=3D"2">));</font></font></p><font face=3D"Consolas" size=3D"2"><font face=
=3D"Consolas" size=3D"2">
<p>}</p></font></font></div><div><br></div><div>Sorry, could not resist :-P=
=C2=A0</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1367_1157515405.1444575103393--
------=_Part_1366_1511276333.1444575103393--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 09:09:22 -0700 (PDT)
Raw View
------=_Part_158_1224148782.1444579762634
Content-Type: multipart/alternative;
boundary="----=_Part_159_1731771284.1444579762635"
------=_Part_159_1731771284.1444579762635
Content-Type: text/plain; charset=UTF-8
On Saturday, October 10, 2015 at 9:29:25 PM UTC-4, Gor Nishanov wrote:
>
> >> So do I have to do something like `while(await <expr>)` to actually
> wait on something? Or have I misunderstood something?
>
> If it makes it easier, you can watch last year CppCon presentation from
> about 10 minutes mark. I will slowly go over how awaitables work:
>
> https://youtu.be/KUhSjfSbINE?t=597
>
That's a nice presentation, but I'm not sure how it resolve the problem I
raised.
OK, this is going to be long, because I need to explain at every step
what's going on.
Let's take the case of non-threading cooperative operations. Let's say I
have a simple coroutine that executes 3 processes, awaiting on each one:
<whatever> operation()
{
await Process1();
await Process2();
await Process3();
}
Now, I have someone who calls this operation. This code knows that the
process doesn't immediately terminate, so it will have some other work to
do between calls. But it also has some work to do both before and after the
operation:
void cooperative()
{
//Some processing before starting `operation`.
auto op = operation();
while(!op.ready())
{
op.resume();
//Do some arbitrary processing.
}
//Do some processing that requires `operation` to be complete.
return;
}
Given that `<whatever>` and its associated types implements the appropriate
things to make coroutines work, this should do what it says. It will call
each process in `operation`, and it will not go past the loop until
`operation` has finished.
If this is incorrect, let me know, and you can ignore the rest of this.
Now, let's say that I decide that `cooperative` is getting way too big and
complex to reason about. Maybe the processing before or after has grown.
Maybe there are a half-dozen operations in the function that are being done
in series, so I'm having to repeat a lot of "wait and do stuff" loops. The
reason doesn't matter.
What matters is that I now want to change `cooperative` to be a coroutine.
This means that it's up to the caller to implement the "Do some arbitrary
processing" part. So my new code... well, I want it to look like this:
<whatever2> cooperative_co()
{
//Some processing before starting `operation`.
await operation();
//Do some processing that requires `operation` to be complete.
return;
}
Let's assume that `<whatever>` from `operation` implements whatever `await`
requires. Is this implementation of `cooperative_co` the equivalent of
`cooperative`?
I believe that they're *intended* to be the same, since every example of
how to use `await` strongly suggests that they are. But given P0057, I
don't see how they can be, as it seems to synthesize this:
<whatever2> cooperative_co()
{
//Some processing before starting `operation`.
{
auto &&e = operator await(operation());
if(e.await_ready())
e.await_resume();
else
{
e.await_suspend(my_handle);
<SUSPEND_RESUME_POINT>
e.await_resume();
}
}
//Do some processing that requires `operation` to be complete.
return;
}
If the caller to `cooperative_co` resumes the coroutine, then execution
will continue from the <SUSPEND_RESUME_POINT>. So `coroutine_co` will
resume `operation`... but it will only resume it *once*. When `operation`
halts the second time, control transfers back to `coroutine_co` just after
the call to `e.await_resume`.
And then processing goes awry; execution continues straight into processing
that assumes `operation` has completed. That's bad.
What am I missing here? Is the intent that `await` doesn't *actually* wait
until the process has completed? If so, what's the point? When would you
ever use `await` outside of some loop that makes sure the process is
actually finished?
And how do you implement that loop? Does it look like this:
<whatever2> cooperative_co()
{
//Some processing before starting `operation`.
auto op = operation();
while(!await op);
//Do some processing that requires `operation` to be complete.
return;
}
Does that even work? Do you have to manually use `operator await`?
Or is this kind of looping `await` supposed to be implemented by the
various machinery that I glossed over (`<whatever2>`, `<whatever>`, and the
result of `operator await`)?
Or is there something that I'm completely missing here? Because examples
from the video appear to exhibit the exact same flaw.
Take your example of `lock_or_suspend`. If the lock couldn't be immediately
acquired, it will create a thread that will wait for the lock. Then, the
`await` expansion will suspend the coroutine.
But there is nothing in the `await` expansion which will verify that the
lock has been acquired *before* allowing the coroutine to proceed ahead.
There is no loop over the `e.await_ready`. There is no thread.join. There
is nothing that would even conceptually ensure this.
If the caller of `DoSomething` resumes the coroutine after it is suspended,
there's no guarantee that the lock has been acquired. `await` is defined as
a one-time test, not a continuous poll.
So what exactly is `await` for, if it can't even ensure that the conditions
to continue have been met?
--
---
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_159_1731771284.1444579762635
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, October 10, 2015 at 9:29:25 PM UTC-4, Gor Nis=
hanov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div>>> So do I have to do something like `while(await <expr>)` =
to actually wait on something? Or have I misunderstood something?</div><div=
><br></div><div>If it makes it easier, you can watch last year CppCon prese=
ntation from about 10 minutes mark. I will slowly go over how awaitables wo=
rk:</div><div><br></div><div><a href=3D"https://youtu.be/KUhSjfSbINE?t=3D59=
7" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'https=
://youtu.be/KUhSjfSbINE?t\075597';return true;" onclick=3D"this.href=3D=
'https://youtu.be/KUhSjfSbINE?t\075597';return true;">https://youtu=
..be/KUhSjfSbINE?<wbr>t=3D597</a></div></div></blockquote><div><br>That'=
s a nice presentation, but I'm not sure how it resolve the problem I ra=
ised.<br><br>OK, this is going to be long, because I need to explain at eve=
ry step what's going on.<br><br>Let's take the case of non-threadin=
g cooperative operations. Let's say I have a simple coroutine that exec=
utes 3 processes, awaiting on each one:<br><br><div class=3D"prettyprint" s=
tyle=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 1=
87); border-style: solid; border-width: 1px; word-wrap: break-word;"><code =
class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #=
008;" class=3D"styled-by-prettify"><whatever></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> operation()<br>{<br>=C2=A0 =C2=A0=
await Process1();<br>=C2=A0 =C2=A0 await Process2();<br>=C2=A0 =C2=A0 awai=
t Process3();<br>}</span></div></code></div><br>Now, I have someone who cal=
ls this operation. This code knows that the process doesn't immediately=
terminate, so it will have some other work to do between calls. But it als=
o has some work to do both before and after the operation:<br><br><div clas=
s=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-col=
or: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: =
break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> cooperative</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #=
800;" class=3D"styled-by-prettify">//Some processing before starting `opera=
tion`.</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> op </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> operation</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">while</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(!</span><span style=3D"color: #000;" class=3D"styled-by-prettify">op</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">ready</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">())</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 op</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">resume</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">();</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">//Do some =
arbitrary processing.</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"color: =
#800;" class=3D"styled-by-prettify">//Do some processing that requires `ope=
ration` to be complete.</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">}</span></div></code></div><br>Given that `<whatever=
>` and its associated types implements the appropriate things to make co=
routines work, this should do what it says. It will call each process in `o=
peration`, and it will not go past the loop until `operation` has finished.=
<br><br>If this is incorrect, let me know, and you can ignore the rest of t=
his.<br><br>Now, let's say that I decide that `cooperative` is getting =
way too big and complex to reason about. Maybe the processing before or aft=
er has grown. Maybe there are a half-dozen operations in the function that =
are being done in series, so I'm having to repeat a lot of "wait a=
nd do stuff" loops. The reason doesn't matter.<br><br>What matters=
is that I now want to change `cooperative` to be a coroutine. This means t=
hat it's up to the caller to implement the "Do some arbitrary proc=
essing" part. So my new code... well, I want it to look like this:<br>=
<br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250=
); border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px=
; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span style=3D"color: #008;" class=3D"styled-by-prettify"><what=
ever2></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
cooperative_co()<br>{<br>=C2=A0 =C2=A0 //Some processing before starting `o=
peration`.<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 await operation();<br>=C2=A0 =
=C2=A0 <br>=C2=A0 =C2=A0 //Do some processing that requires `operation` to =
be complete.<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 return;<br>}</span></div></=
code></div><br>Let's assume that `<whatever>` from `operation` im=
plements whatever `await` requires. Is this implementation of `cooperative_=
co` the equivalent of `cooperative`?<br><br>I believe that they're <i>i=
ntended</i> to be the same, since every example of how to use `await` stron=
gly suggests that they are. But given P0057, I don't see how they can b=
e, as it seems to synthesize this:<br><br><div class=3D"prettyprint" style=
=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187);=
border-style: solid; border-width: 1px; word-wrap: break-word;"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;=
" class=3D"styled-by-prettify"><whatever2></span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> cooperative_co()<br>{<br>=C2=A0 =C2=
=A0 //Some processing before starting `operation`.<br>=C2=A0 =C2=A0 <br>=C2=
=A0 =C2=A0 {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 auto &&e =3D operator a=
wait(operation());<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 if(e.await_ready())<br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 e.await_resume();<br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 else<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 {<br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 e.await_suspend(my_handle);<br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify"><SUSPEND_RESUME_POINT></span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 e.await_resume();<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>=C2=A0 =C2=A0 =
}<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 //Do some processing that requires `op=
eration` to be complete.<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 return;<br>}</s=
pan></div></code></div><br>If the caller to `cooperative_co` resumes the co=
routine, then execution will continue from the <SUSPEND_RESUME_POINT>=
.. So `coroutine_co` will resume `operation`... but it will only resume it <=
i>once</i>. When `operation` halts the second time, control transfers back =
to `coroutine_co` just after the call to `e.await_resume`.<br><br>And then =
processing goes awry; execution continues straight into processing that ass=
umes `operation` has completed. That's bad.<br><br>What am I missing he=
re? Is the intent that `await` doesn't <i>actually</i> wait until the p=
rocess has completed? If so, what's the point? When would you ever use =
`await` outside of some loop that makes sure the process is actually finish=
ed?<br><br>And how do you implement that loop? Does it look like this:<br><=
br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250)=
; border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px;=
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprett=
yprint"><span style=3D"color: #008;" class=3D"styled-by-prettify"><whate=
ver2></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> c=
ooperative_co()<br>{<br>=C2=A0 =C2=A0 //Some processing before starting `op=
eration`.<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 auto op =3D operation();<br>=
=C2=A0 =C2=A0 while(!await op);<br>=C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 //Do som=
e processing that requires `operation` to be complete.<br>=C2=A0 =C2=A0 <br=
>=C2=A0 =C2=A0 return;<br>}</span></div></code></div><br>Does that even wor=
k? Do you have to manually use `operator await`?<br><br>Or is this kind of =
looping `await` supposed to be implemented by the various machinery that I =
glossed over (`<whatever2>`, `<whatever>`, and the result of `o=
perator await`)?<br><br>Or is there something that I'm completely missi=
ng here? Because examples from the video appear to exhibit the exact same f=
law.<br><br>Take your example of `lock_or_suspend`. If the lock couldn'=
t be immediately acquired, it will create a thread that will wait for the l=
ock. Then, the `await` expansion will suspend the coroutine.<br><br>But the=
re is nothing in the `await` expansion which will verify that the lock has =
been acquired <i>before</i> allowing the coroutine to proceed ahead. There =
is no loop over the `e.await_ready`. There is no thread.join. There is noth=
ing that would even conceptually ensure this.<br><br>If the caller of `DoSo=
mething` resumes the coroutine after it is suspended, there's no guaran=
tee that the lock has been acquired. `await` is defined as a one-time test,=
not a continuous poll.<br><br>So what exactly is `await` for, if it can=
9;t even ensure that the conditions to continue have been met?<br></div></d=
iv>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_159_1731771284.1444579762635--
------=_Part_158_1224148782.1444579762634--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Mon, 12 Oct 2015 00:15:53 +0800
Raw View
--047d7bea2f98e0fc970521d686c2
Content-Type: text/plain; charset=UTF-8
Hi Gor,
2015-10-11 21:17 GMT+08:00 Gor Nishanov <gornishanov@gmail.com>:
> Hi Tongari:
>
> I do not understand how decision whether coroutine_handle<> has RAII
> semantic or not has any bearing on the example you shown.
> The behavior of
>
> std::future<void> f() {
>
> Resource res(...);
>
> await std::suspend_always{};
>
> }
>
> depends solely on what semantics of the future and suspend_always is.
>
> If future returned here has RAII semantics, like the future produced by
> std::async, then we will have deadlock as the future destructor will block
> forever in its destructor. If future has "leak async" semantic like the
> future returned from promise.get_future(), it will result in a leak. In
> C++17 or later, I would like to have a better vocabulary type that supports
> cancellation, let's call it STLv2 future, in that case, it will cancel the
> coroutine in its destructor, thus avoiding the leak.
>
> suspend_always have the semantics implied by its name. Unconditional
> suspend at this point. If customer requested this, coroutine will suspend.
> Period. If you disagree with semantics of suspend_always or would like it
> to have more obscure name that is fine. Also, I consider suspend_always to
> be a library class. It is not special in any way form compiler perspective.
> I included it in the proposal, because it is something that I felt people
> will be writing themselves anyways, so putting it in the standard library
> will allow to avoid the repetition and give some common vocabulary name.
> (It may be not the best name, I am open to suggestions. Earlier it was
> suspend_now).
>
I have no problem with suspend_always, I like it and I use it. What I was
trying to say is that when it is used with `std::future`, given the current
raw-semantic, the behavior is dangerous, the memory & resource leak, and if
you wait on it, it hangs. But given unique-semantic and ownership-transfer,
the coroutine's dtor will unwind the stack, throw an exception if you wait
on it (i.e. broken promise), which is a much safer behavior IMO.
> In both cases, we discuss what semantics a library writer wants to impart
> to the future and suspend_always. That behavior is what library writer
> designs. How coroutine_handle behaves has no bearing on that decision.
>
The author of coroutine-promise has no knowledge about what the user will
await in the function, how could he ensure that something like `await
std::suspend_always{}` would never happen, or how could he make it safe if
that happens?
And the author of the awaitable has no knowledge about inside what
coroutine will it be used, how could he ensure that the coroutine-promise
will handle it in in a safe manner? for example, std::suspend_always just
suspends the coroutine, but how could it tell the coroutine-promise that it
should cancel the coroutine afterwards?
For them to collaborate safely, there must be a protocol in-between, and
that is ownership-transfer.
> *On future evolution*
>
> There reason I added the section about it in P0054 was to show that such
> exploration is possible in the future. It should not stop progress on this
> proposal.
>
>>
>> What if the future exploration is not compatible with the current design?
>> that's my concern.
>>
>
> I think both the "automatically awaited awaitables" idea of P0054 and your
> idea about async mofified on a function are compatible and can be built on
> top of P0057.
>
Not quite, my idea requires a manual "async" mark before the function body,
to distinguish the normal context and resumable context for context-based
overloading. Your design doesn't require that (which in itself is a good
thing), so they're incompatible in some aspects.
> *On awaitable return_value*
>
>>
>>> I store a reference to the expression (lvalue or temporary on the
>>> coroutine frame) and give a chance to consumer, potentially running on a
>>> different thread to observe it before semicolon at the end of full
>>> expression destroys the value (or leaving the scope and stopping at final
>>> suspend destroys the lvalue that I was trying to return)
>>>
>>
>> I kinda get the idea, but how can the consumer notify the promise that it
>> takes the value?
>>
>
> Consumer will resume the coroutine when it is consumed the value.
>
Does it look like this?
```c++
T await_resume()
{
T ret(get_rv_ref_frome_the_promise());
resume_the_coroutine();
return ret;
}
```
So my guess that this trick relies on RVO and copy-ellision and cannot
return a T&& is correct, right?
> *On final_suspend*
>
>
>> What is the difference between this:
>>> ```c++
>>> auto final_suspend()
>>> {
>>> struct awaiter
>>> {
>>> promise_type * me;
>>> bool await_ready() { return false; }
>>> void await_resume() {}
>>> bool await_suspend(coroutine_handle<>) {
>>> auto need_suspending = (me->decrement_refcount() > 0);
>>> return need_suspending;
>>> }
>>> };
>>> return awaiter{this};
>>> }
>>> ```
>>> and this:
>>> ```c++
>>> bool final_suspend()
>>> {
>>> auto need_suspending = (decrement_refcount() > 0); ((<-- HERE))
>>> return need_suspending;
>>> }
>>> ```
>>>
>>
> Just like with initial_suspend, you need to think where PrepareForSuspend
> goes relative to a call to final_suspend.
> Note, that as soon as you do (decrement_refcount() > 0), a racing thread
> that has an owning handle to a coroutine will decrement the refcount,
> observe that it is zero now and destroys the coroutine while the current
> thread is still at the semicolon marked with HERE tag in the example above.
>
So the problem is the race condition in PrepareForSuspend() while other
thread is destroying the coroutine?
Makes sense then, sorry I didn't see it because in my implementation the
PrepareForSuspend() for final_suspend is just a noop.
--
---
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/.
--047d7bea2f98e0fc970521d686c2
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Gor,<br><div class=3D"gmail_extra"><br><div class=3D"gm=
ail_quote">2015-10-11 21:17 GMT+08:00 Gor Nishanov <span dir=3D"ltr"><<a=
href=3D"mailto:gornishanov@gmail.com" target=3D"_blank">gornishanov@gmail.=
com</a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div>Hi Tongari:</=
div><div><br></div><div>I do not understand how decision whether coroutine_=
handle<> has RAII semantic or not has any bearing on the example you =
shown.</div><div>The behavior of</div><span class=3D""><div><br></div><div>=
<p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">st=
d::future<</font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">void</font></font></font><font face=
=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2">> f() {</fon=
t></font></p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" siz=
e=3D"2">
<p> =C2=A0=C2=A0 Resource res(...);</p>
</font></font><p><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas"=
size=3D"2"> </font></font><font color=3D"#0000ff" face=3D"Consolas" size=
=3D"2"><font color=3D"#0000ff" face=3D"Consolas" size=3D"2"><font color=3D"=
#0000ff" face=3D"Consolas" size=3D"2">=C2=A0=C2=A0 await</font></font></fon=
t><font face=3D"Consolas" size=3D"2"><font face=3D"Consolas" size=3D"2"> st=
d::suspend_always{};</font></font></p><font face=3D"Consolas" size=3D"2"><f=
ont face=3D"Consolas" size=3D"2">
<p>}</p></font></font></div><div><br></div></span><div>depends solely on wh=
at semantics of the future and suspend_always is.</div><div><br></div><div>=
If future returned here has RAII semantics, like the future produced by std=
::async, then we will have deadlock as the=C2=A0future destructor=C2=A0will=
block forever in its destructor. If future has "leak async" sema=
ntic like the future returned from promise.get_future(), it will result in =
a leak. In C++17 or later, I would like to have a better vocabulary type th=
at supports cancellation, let's call it STLv2 future, in that case, it =
will cancel the coroutine in its destructor, thus avoiding the leak.</div><=
div><br></div><div>suspend_always have the semantics implied by its name. U=
nconditional suspend at this point. If customer requested this, coroutine w=
ill suspend. Period. If you disagree with semantics of suspend_always or wo=
uld like it to have more obscure name that is fine. Also, I consider suspen=
d_always to be a library class. It is not special in any way form compiler =
perspective. I included it in the proposal, because it is something that I =
felt people will be writing themselves anyways, so putting it in the standa=
rd library will allow to avoid the repetition and give some common vocabula=
ry name. (It may be not the best name, I am open to suggestions. Earlier it=
was suspend_now).</div></div></blockquote><div><br></div><div>I have no pr=
oblem with suspend_always, I like it and I use it. What I was trying to say=
is that when=C2=A0it is used with `std::future`, given the current raw-sem=
antic, the behavior is dangerous, the memory & resource leak, and if yo=
u wait on it, it hangs. But given unique-semantic and ownership-transfer, t=
he coroutine's dtor will unwind the stack, throw an exception if you wa=
it on it (i.e. broken promise), which is a much safer behavior IMO.</div><d=
iv>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div>In both ca=
ses, we discuss what semantics a library writer wants to impart to the futu=
re and suspend_always. That behavior is what library writer designs. How co=
routine_handle behaves has no bearing on that decision.</div></div></blockq=
uote><div><br></div><div>The author of coroutine-promise has no knowledge a=
bout what the user will await in the function, how could he ensure that som=
ething like=C2=A0`await std::suspend_always{}` would never happen, or how c=
ould he make it safe if that happens?</div><div><br></div><div>And the auth=
or of the awaitable has no knowledge about inside what coroutine will it be=
used, how=C2=A0could he ensure that the coroutine-promise will handle it i=
n in a safe manner? for example, std::suspend_always just suspends the coro=
utine, but how could it tell the coroutine-promise that it should cancel th=
e coroutine afterwards?</div><div><br></div><div>For them to collaborate sa=
fely, there must be a protocol in-between, and that is ownership-transfer.<=
/div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px=
0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bor=
der-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div><st=
rong>On future evolution</strong></div><span class=3D""><div><br>There reas=
on=C2=A0I added the section about it in P0054 was to show that such explora=
tion is possible in the future. It should not stop progress on this proposa=
l.</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex=
;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;=
border-left-style:solid"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><=
div><br></div><div>What if the future exploration is not compatible with th=
e current design? that's my concern.</div></div></div></div></blockquot=
e><div><br></div></span><div>I=C2=A0think both the "automatically awai=
ted awaitables" idea of P0054 and your idea about async mofified on a =
function are compatible and can be built on top of P0057.=C2=A0<br></div></=
div></blockquote><div><br></div><div>Not quite, my idea requires a manual &=
quot;async" mark before the function body, to distinguish the normal c=
ontext and resumable context for context-based overloading. Your design doe=
sn't require that (which in itself is a good thing), so they're inc=
ompatible in some aspects.</div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left=
-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir=
=3D"ltr"><span class=3D""><div><strong>On awaitable return_value</strong></=
div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;pad=
ding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bord=
er-left-style:solid"><div dir=3D"ltr"><div><div class=3D"gmail_quote"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left=
:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-s=
tyle:solid"><div dir=3D"ltr"><div><br></div><div>I store=C2=A0a reference t=
o the expression (lvalue or temporary on the coroutine frame) and give a ch=
ance to consumer, potentially running on a different thread to observe it b=
efore semicolon at the end of full expression destroys the value (or leavin=
g the scope and stopping at final suspend destroys the lvalue that I was tr=
ying to return)</div></div></blockquote><div><br></div><div>I kinda get the=
idea, but how can the consumer notify the promise that it takes the value?=
<br></div></div></div></div></blockquote><div><br></div></span><div>Consume=
r will=C2=A0resume the coroutine when it is consumed the value.</div></div>=
</blockquote><div><br></div><div>Does it look like this?</div><div>```c++</=
div><div>T await_resume()<br></div><div>{</div><div>=C2=A0 =C2=A0 T ret(get=
_rv_ref_frome_the_promise());</div><div>=C2=A0 =C2=A0=C2=A0resume_the_corou=
tine();<br></div><div>=C2=A0 =C2=A0 return ret;</div><div>}</div><div>```=
=C2=A0</div><div><br></div><div>So my guess that this trick relies on RVO a=
nd copy-ellision and cannot return a T&& is correct, right?</div><d=
iv>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><strong>On final_susp=
end</strong></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204=
,204);border-left-width:1px;border-left-style:solid"><div dir=3D"ltr"><div>=
<div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);bor=
der-left-width:1px;border-left-style:solid"><div dir=3D"ltr"><div><span cla=
ss=3D"">What is the difference between this:<br>```c++<br>auto final_suspen=
d()<br>{<br>=C2=A0 =C2=A0 struct awaiter<br>=C2=A0 =C2=A0 {<br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 promise_type * me;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool aw=
ait_ready() { return false; }<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 void await_res=
ume() {}<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 bool await_suspend(coroutine_handle=
<>) {<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 auto need_suspendi=
ng =3D (me->decrement_refcount() > 0);<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 return need_suspending;<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>=
=C2=A0 =C2=A0 };<br>=C2=A0 =C2=A0 return awaiter{this};<br>}<br>```<br>and =
this:<br>```c++<br>bool final_suspend()<br>{<br></span>=C2=A0 =C2=A0 auto n=
eed_suspending =3D (decrement_refcount() > 0); ((<-- HERE))<br>=C2=A0=
=C2=A0=C2=A0 return need_suspending;<br>}<br>```<br></div></div></blockquot=
e></div></div></div></blockquote><div><br></div><div>=C2=A0Just like with i=
nitial_suspend, you need to think where PrepareForSuspend goes relative to =
a call to final_suspend.</div><div>Note, that as soon as you do (decrement_=
refcount() > 0), a racing thread that has an owning handle to a coroutin=
e will decrement the refcount, observe that it is zero now and destroys the=
coroutine while the current thread is still at the semicolon marked with H=
ERE tag in the example above.</div></div></blockquote><div><br></div><div>S=
o the problem is the race condition in PrepareForSuspend() while other thre=
ad is destroying the coroutine?</div><div>Makes sense then, sorry I didn=
9;t see it because in my implementation the PrepareForSuspend() for final_s=
uspend is just a noop.</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bea2f98e0fc970521d686c2--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 10:42:20 -0700 (PDT)
Raw View
------=_Part_4457_1560093013.1444585340966
Content-Type: multipart/alternative;
boundary="----=_Part_4458_1361010648.1444585340966"
------=_Part_4458_1361010648.1444585340966
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 9:09:23 AM UTC-7, Nicol Bolas wrote:
>
> If this is incorrect, let me know, and you can ignore the rest of this.
>
This part is fine:
<whatever> operation()
{
await Process1();
await Process2();
await Process3();
}
But I think the rest is not how I would approach the cooperative
single-threaded multitasking.
I think what you need is a queue of work, that will be filled with
coroutine handles that are ready to execute.
In initial_suspend() every coroutine participating in that system will
place its handle into the ready queue and suspend.
await Process1(), will link coroutine_handle of the operation coroutine to
a completion of Process1 coroutine.
When Process1() completes, (say in its final_suspend) it will post the
coroutine handles of all of the coroutines which are waiting on it to the
ready queue.
No coroutine should ever call resume() directly. That is responsibility of
your scheduler in the main program, which looks like this.
CoroutineHandleQueue q;
int main() {
Start The Initial Coroutine
while (auto h = q.pull()) { // will block if q is empty
if (!h) break; // I am using empty coroutine_handle as a singnal to
shutdown the loop
h.resume();
}
}
--
---
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_4458_1361010648.1444585340966
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Sunday, October 11, 2015 at 9:09:23 AM UTC-7, N=
icol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>If this is incorrect, let me know, and you can ignore the rest of =
this.<br></div></div></blockquote><div><br></div><div>This part is fine:</d=
iv><div><br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb=
(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250=
);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify"><whatever></span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> operation()<br>{<br>=
=C2=A0 =C2=A0 await Process1();<br>=C2=A0 =C2=A0 await Process2();<br>=C2=
=A0 =C2=A0 await Process3();<br>}<br></span></div></code></div><div><br></d=
iv><div>But I think the rest is not how I would approach the cooperative si=
ngle-threaded multitasking.</div><div>I think what you need is a queue of w=
ork, that will be filled with coroutine handles that are ready to execute.<=
/div><div><br></div><div>In initial_suspend() every coroutine participating=
in that system will place its handle into the ready queue and suspend.</di=
v><div>await Process1(), will link coroutine_handle of the operation corout=
ine to a completion of Process1 coroutine.</div><div><br></div><div>When Pr=
ocess1() completes, (say in its final_suspend) it will post the coroutine h=
andles of all of the coroutines which are waiting on it to the ready queue.=
</div><div>No coroutine should ever call resume() directly. That is respons=
ibility of your scheduler in the main program, which looks like this.</div>=
<div><br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(18=
7, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);"=
><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">CoroutineHandleQueue</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> q</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br><br></span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">int</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> main</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0</span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">Start</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">The</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #606;" class=3D"styled-by-prettify">Initial</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Coroutine</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">while</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> h </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> q</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">pull</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">())</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"=
styled-by-prettify">// will block if q is empty</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(!</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">h</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
break</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// I am using empty cor=
outine_handle as a singnal to shutdown the loop</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 h</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">resume</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span></div></code></div><div><br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4458_1361010648.1444585340966--
------=_Part_4457_1560093013.1444585340966--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 12:58:54 -0700 (PDT)
Raw View
------=_Part_4622_57058346.1444593535096
Content-Type: multipart/alternative;
boundary="----=_Part_4623_1291684279.1444593535096"
------=_Part_4623_1291684279.1444593535096
Content-Type: text/plain; charset=UTF-8
What am I doing! There is no need for if(!h) break; Scheduler loop is even
simpler.
CoroutineHandleQueue q;
>
> int main() {
> Start The Initial Coroutine
> while (auto h = q.pull()) h.resume();
> }
>
>
--
---
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_4623_1291684279.1444593535096
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">What am I doing! There is no need for if(!h) break;=C2=A0S=
cheduler loop is even simpler.<br><br><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(=
204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr"><div style=3D"border: 1px solid rgb(187, 187, 187); border-image: =
none; -ms-word-wrap: break-word; background-color: rgb(250, 250, 250);"><co=
de><div><span style=3D"color: rgb(102, 0, 102);">CoroutineHandleQueue</span=
><span style=3D"color: rgb(0, 0, 0);"> q</span><span style=3D"color: rgb(10=
2, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br><br></span><s=
pan style=3D"color: rgb(0, 0, 136);">int</span><span style=3D"color: rgb(0,=
0, 0);"> main</span><span style=3D"color: rgb(102, 102, 0);">()</span><spa=
n style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102=
, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0</span=
><span style=3D"color: rgb(102, 0, 102);">Start</span><span style=3D"color:=
rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 0, 102);">The</span>=
<span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102,=
0, 102);">Initial</span><span style=3D"color: rgb(0, 0, 0);"> </span><span=
style=3D"color: rgb(102, 0, 102);">Coroutine</span><span style=3D"color: r=
gb(0, 0, 0);"><br>=C2=A0 =C2=A0</span><span style=3D"color: rgb(0, 0, 136);=
">while</span><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"c=
olor: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(0, 0, 136);">aut=
o</span><span style=3D"color: rgb(0, 0, 0);"> h </span><span style=3D"color=
: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0);"> q</spa=
n><span style=3D"color: rgb(102, 102, 0);">.</span><span style=3D"color: rg=
b(0, 0, 0);">pull</span><span style=3D"color: rgb(102, 102, 0);">())</span>=
<span style=3D"color: rgb(0, 0, 0);">=C2=A0</span><span style=3D"color: rgb=
(0, 0, 0);">h</span><span style=3D"color: rgb(102, 102, 0);">.</span><span =
style=3D"color: rgb(0, 0, 0);">resume</span><span style=3D"color: rgb(102, =
102, 0);">();</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span s=
tyle=3D"color: rgb(102, 102, 0);">}</span><span style=3D"color: rgb(0, 0, 0=
);"><br></span></div></code><div><br></div></div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4623_1291684279.1444593535096--
------=_Part_4622_57058346.1444593535096--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 14:05:36 -0700 (PDT)
Raw View
------=_Part_3935_1656962655.1444597536144
Content-Type: multipart/alternative;
boundary="----=_Part_3936_1212121377.1444597536144"
------=_Part_3936_1212121377.1444597536144
Content-Type: text/plain; charset=UTF-8
I may have had an epiphany regarding `await`. But first, I think there are
some things you said that aren't correct, according to P0057:
In initial_suspend() every coroutine participating in that system will
> place its handle into the ready queue and suspend.
`initial_suspend` is not given a coroutine_handle. Indeed, I'm not sure how
a coroutine promise object is given access to its handle. You can convert
from a handle to its promise, but not the other way around.
However, on to the epiphany.
All of the examples of code using `await` give a general, high-level idea
of what the keyword does: it suspends the current function until the given
object is finished, for some definition of "finished".
And the low-level idea of `await` was clear from P0057. What I couldn't
reconcile was how you get from the low-level details to the high-level
idea. The "mid-level" concept of `await`, if you will.
Now, I think I get it. And the example of `lock_or_suspend` is what made it
clear to me. From a mid-level perspective, `await` means exactly and only
this:
The continued execution of this function (until the next await/return) will
take place at a time and in a fashion defined by *the object being awaited
on*.
It was that last part that kept throwing me off, because it's
counter-intuitive considering most of the examples out there.
But considering the relationship between await and `future::then`, it makes
sense. If you're running a task in a thread, and you ".then" that future,
that task runs on the thread the future is running on (probably). It almost
certainly isn't going to run on *this* thread.
So control over "scheduling" is created by the operation being waited on,
not by the coroutine doing the waiting.
The problem with this is that making things execute in the correct order
requires some from of global God-object that everyone is registered to when
they await on a coroutine. By all rights, it should be able to be a stack
object, created by the ultimate caller of the first coroutine that
initiated the operation.
But I don't know of a way to do that. Even if you pass it to every single
coroutine as a parameter, you can't get it to where it needs to go: the
`await_suspend` call in the awaiter object.
The stack can't be in the coroutine promise, as each coroutine has its own
promise object. And there is no way to make different coroutine promise
objects talk to one another.
I don't see a way to avoid having a global "scheduler". And that sounds
like a *serious* flaw in the await model. If there has to be a scheduler
(or as I prefer to see it, a stack of coroutine_handles), then it should be
something that can be local.
I want to be able to have dozens of such stacks, all in various states of
operation. All of them should be completely independent of each other, but
they ought to be able to use the same types.
--
---
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_3936_1212121377.1444597536144
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I may have had an epiphany regarding `await`. But first, I=
think there are some things you said that aren't correct, according to=
P0057:<br><br><div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-=
left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=3D"gmail_quot=
e">In initial_suspend() every coroutine participating in that system will p=
lace its handle into the ready queue and suspend.</blockquote><div><br>`ini=
tial_suspend` is not given a coroutine_handle. Indeed, I'm not sure how=
a coroutine promise object is given access to its handle. You can convert =
from a handle to its promise, but not the other way around.<br><br>However,=
on to the epiphany.<br><br>All of the examples of code using `await` give =
a general, high-level idea of what the keyword does: it suspends the curren=
t function until the given object is finished, for some definition of "=
;finished".<br><br>And the low-level idea of `await` was clear from P0=
057. What I couldn't reconcile was how you get from the low-level detai=
ls to the high-level idea. The "mid-level" concept of `await`, if=
you will.<br><br>Now, I think I get it. And the example of `lock_or_suspen=
d` is what made it clear to me. From a mid-level perspective, `await` means=
exactly and only this:<br><br>The continued execution of this function (un=
til the next await/return) will take place at a time and in a fashion defin=
ed by <u><i>the object being awaited on</i></u>.<br><br>It was that last pa=
rt that kept throwing me off, because it's counter-intuitive considerin=
g most of the examples out there.<br><br>But considering the relationship b=
etween await and `future::then`, it makes sense. If you're running a ta=
sk in a thread, and you ".then" that future, that task runs on th=
e thread the future is running on (probably). It almost certainly isn't=
going to run on <i>this</i> thread.<br><br>So control over "schedulin=
g" is created by the operation being waited on, not by the coroutine d=
oing the waiting.<br><br>The problem with this is that making things execut=
e in the correct order requires some from of global God-object that everyon=
e is registered to when they await on a coroutine. By all rights, it should=
be able to be a stack object, created by the ultimate caller of the first =
coroutine that initiated the operation.<br><br>But I don't know of a wa=
y to do that. Even if you pass it to every single coroutine as a parameter,=
you can't get it to where it needs to go: the `await_suspend` call in =
the awaiter object.<br><br>The stack can't be in the coroutine promise,=
as each coroutine has its own promise object. And there is no way to make =
different coroutine promise objects talk to one another.<br><br>I don't=
see a way to avoid having a global "scheduler". And that sounds =
like a <i>serious</i> flaw in the await model. If there has to be a schedul=
er (or as I prefer to see it, a stack of coroutine_handles), then it should=
be something that can be local.<br><br>I want to be able to have dozens of=
such stacks, all in various states of operation. All of them should be com=
pletely independent of each other, but they ought to be able to use the sam=
e types.<br></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3936_1212121377.1444597536144--
------=_Part_3935_1656962655.1444597536144--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 14:23:09 -0700 (PDT)
Raw View
------=_Part_4738_1896530757.1444598589622
Content-Type: multipart/alternative;
boundary="----=_Part_4739_1739608367.1444598589623"
------=_Part_4739_1739608367.1444598589623
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 2:05:36 PM UTC-7, Nicol Bolas wrote:
>
> `initial_suspend` is not given a coroutine_handle. Indeed, I'm not sure
> how a coroutine promise object is given access to its handle. You can
> convert from a handle to its promise, but not the other way around.
>
Note that initial_suspend() returns awaitable. Awaitable is given a
coroutine_handle<> for the enclosing coroutine.
auto initial_suspend() {
struct awaiter {
bool await_ready() { return false; }
void await_suspend(coroutine_handle<> h) { scheduler.post(h); }
void await_resume();
};
return awaiter{};
}
In a simple case, initial_suspend() could be just
suspend_always initial_suspend() { return{}; } // for simple generator
or
suspend_never initial_suspend() { return{}; } // for fire and forget future
with no RAII
I want to be able to have dozens of such stacks, all in various states of
> operation. All of them should be completely independent of each other, but
> they ought to be able to use the same types.
>
I don't think I understand. For me, coroutine is just a fancy way of
providing a callback and a state. If you know how to write async code with
callbacks, you can write it with coroutines, since now the callback could
be just resume this coroutine at this point. And scheduler for me, I am
developing for Windows, is Windows threadpool.
In the world of boost, the scheduler is io_service and your handcrafted
threadpool you build by calling io_service::run() function.
P0055: On Interactions Between Coroutines and Networking Library shows how
async APIs can automatically return a proper awaitable that can have
"negative overhead" compared to regular callbacks.
With respect to coroutine return type, we don't have a good one yet.
Hopefully, somebody will come up with one. When coroutines are on the path
to C++17, I may focus on a good task/future type that will have
cancellation and be zero-overhead, unless somebody else beat me to it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4739_1739608367.1444598589623
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Sunday, October 11, 2015 at 2:05:36 PM UTC-7, N=
icol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div>`initial_suspend` is not given a coroutine_handle. Indeed, I&=
#39;m not sure how a coroutine promise object is given access to its handle=
.. You can convert from a handle to its promise, but not the other way aroun=
d.<br></div></div></div></blockquote><div><br></div><div>Note that initial_=
suspend() returns awaitable. Awaitable is given a coroutine_handle<> =
for the enclosing coroutine.</div><div><br></div><div class=3D"prettyprint"=
style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; back=
ground-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=
=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> in=
itial_suspend</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> awaiter </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color: #008;" class=3D"styled-by-prettify">bool</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> await_ready<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">false</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> await_suspend</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">coro=
utine_handle</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
"><></span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
h</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> scheduler</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">post</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">h</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> aw=
ait_resume</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> awa=
iter</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{};</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></di=
v><div><br><br></div><div>In a simple case, initial_suspend() could be just=
=C2=A0</div><div><br></div><div class=3D"prettyprint" style=3D"border: 1px =
solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250,=
250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">suspend_always initia=
l_suspend</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{};</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>// for simple generator</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"><br>=C2=A0 =C2=A0</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">or</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> <br>suspend_never initial_suspend</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">return</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{}=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #800;" class=3D"styled-by-prettify">// for fire and forget future with n=
o RAII</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span></div></code></div><div><br></div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><div><div>I want to be able to have dozens of s=
uch stacks, all in various states of operation. All of them should be compl=
etely independent of each other, but they ought to be able to use the same =
types.<br></div></div></div></blockquote><div><br></div><div>I don't th=
ink I understand. For me, coroutine is just a fancy way of providing a call=
back and a state. If you know how to write async code with callbacks, you c=
an write it with coroutines, since now the callback could be just resume th=
is coroutine at this point. And scheduler for me, I am developing for Windo=
ws, is Windows threadpool.=C2=A0</div><div>In the world of boost, the sched=
uler is io_service and your handcrafted threadpool you build by calling io_=
service::run() function.</div><div><br></div><div>P0055: On Interactions Be=
tween Coroutines and Networking Library shows how async APIs can automatica=
lly return a proper awaitable that can have "negative overhead" c=
ompared to regular callbacks.</div><div><br></div><div>With respect to coro=
utine return type, we don't have a good one yet. Hopefully, somebody wi=
ll come up with one. When coroutines are on the path to C++17, I may focus =
on a good task/future type that will have cancellation and be zero-overhead=
, unless somebody else beat me to it.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4739_1739608367.1444598589623--
------=_Part_4738_1896530757.1444598589622--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 18:08:46 -0700 (PDT)
Raw View
------=_Part_985_1513695489.1444612126871
Content-Type: multipart/alternative;
boundary="----=_Part_986_441990025.1444612126871"
------=_Part_986_441990025.1444612126871
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 5:23:09 PM UTC-4, Gor Nishanov wrote:
>
> On Sunday, October 11, 2015 at 2:05:36 PM UTC-7, Nicol Bolas wrote:
>>
>> I want to be able to have dozens of such stacks, all in various states of
>> operation. All of them should be completely independent of each other, but
>> they ought to be able to use the same types.
>>
>
> I don't think I understand.
>
It's simple: I want to take your stackless coroutine system and build a
stackful one out of it. I want a full-fledged fiber, which can
cooperatively pause itself, allowing other processing to resume, and return
to exactly where it was. And it *does not matter* how many (awaiting) calls
are between the pausing and the unpausing; I want resuming it to
automatically resume the top-most function of the call stack.
I want to be able to write the C++ equivalent of a Lua coroutine
<http://www.lua.org/pil/9.html>. Good, extensible cooperative coroutines
that anyone can write and use. Without touching globals or having some
massive scheduler object that's shared or anything. I want a resumable
object representing a stackful coroutine that's a regular C++ object that I
can use like a function.
I know resumable functions are a stackless coroutine system, but it's a
low-level system. I would hope that the goal was to be something more than
just a feature to make threading a bit easier.
> With respect to coroutine return type, we don't have a good one yet.
> Hopefully, somebody will come up with one. When coroutines are on the path
> to C++17, I may focus on a good task/future type that will have
> cancellation and be zero-overhead, unless somebody else beat me to it.
>
When I said "use the same types", I mean that all of the stackful
coroutines would return the same type (or a template class, for return
values and such). The point being that, while they're all returning the
same (template) type, they have no other connections besides this. They
don't all take the same parameters or talk to some global or whatever.
So there would be some `coop_coroutine<T>` type which implements all of the
machinery needed for stackful coroutines. Is it possible to write such a
construct in your system?
--
---
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_986_441990025.1444612126871
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, October 11, 2015 at 5:23:09 PM UTC-4, Gor Nisha=
nov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On =
Sunday, October 11, 2015 at 2:05:36 PM UTC-7, Nicol Bolas wrote:<blockquote=
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px =
#ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div>I want to be able t=
o have dozens of such stacks, all in various states of operation. All of th=
em should be completely independent of each other, but they ought to be abl=
e to use the same types.<br></div></div></div></blockquote><div><br></div><=
div>I don't think I understand.</div></div></blockquote><div><br>It'=
;s simple: I want to take your stackless coroutine system and build a stack=
ful one out of it. I want a full-fledged fiber, which can cooperatively pau=
se itself, allowing other processing to resume, and return to exactly where=
it was. And it <i>does not matter</i> how many (awaiting) calls are betwee=
n the pausing and the unpausing; I want resuming it to automatically resume=
the top-most function of the call stack.<br><br>I want to be able to write=
the C++ equivalent of a <a href=3D"http://www.lua.org/pil/9.html">Lua coro=
utine</a>. Good, extensible cooperative coroutines that anyone can write an=
d use. Without touching globals or having some massive scheduler object tha=
t's shared or anything. I want a resumable object representing a stackf=
ul coroutine that's a regular C++ object that I can use like a function=
..<br><br>I know resumable functions are a stackless coroutine system, but i=
t's a low-level system. I would hope that the goal was to be something =
more than just a feature to make threading a bit easier.<br>=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>=
With respect to coroutine return type, we don't have a good one yet. Ho=
pefully, somebody will come up with one. When coroutines are on the path to=
C++17, I may focus on a good task/future type that will have cancellation =
and be zero-overhead, unless somebody else beat me to it.</div></div></bloc=
kquote><div><br>When I said "use the same types", I mean that all=
of the stackful coroutines would return the same type (or a template class=
, for return values and such). The point being that, while they're all =
returning the same (template) type, they have no other connections besides =
this. They don't all take the same parameters or talk to some global or=
whatever.<br><br>So there would be some `coop_coroutine<T>` type whi=
ch implements all of the machinery needed for stackful coroutines. Is it po=
ssible to write such a construct in your system?<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_986_441990025.1444612126871--
------=_Part_985_1513695489.1444612126871--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 18:53:00 -0700 (PDT)
Raw View
------=_Part_132_1368539998.1444614780637
Content-Type: multipart/alternative;
boundary="----=_Part_133_2002982252.1444614780637"
------=_Part_133_2002982252.1444614780637
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 6:08:47 PM UTC-7, Nicol Bolas wrote:
>
> It's simple: I want to take your stackless coroutine system and build a
> stackful one out of it. I want a full-fledged fiber, which can
> cooperatively pause itself, allowing other processing to resume, and return
> to exactly where it was. And it *does not matter* how many (awaiting)
> calls are between the pausing and the unpausing; I want resuming it to
> automatically resume the top-most function of the call stack.
>
Would basing this on real fibers (execution context proposal by Nat and
Oliver P0099) be better? There is a saying: Need a fiber, use a fiber :-) .
Nothing can really beat
ADD RSP,X and SUB RSP,X as a way to allocate, deallocate function frame.
P0057 has cheaper suspend/resume and smaller memory footprint than P0099,
but, if you need is a stack, building it out of (stackless) coroutines may
not be the best idea. Real stack is really really efficient. You pay with
memory and higher context switching cost, but the function call is dirt
cheap.
> I would hope that the goal was to be something more than just a feature to
> make threading a bit easier.
>
P0057 is not a thread replacement, it is a callback replacement. It makes
it easier to express asynchronous state machine in the form of the
imperative control flow.
So there would be some `coop_coroutine<T>` type which implements all of the
> machinery needed for stackful coroutines. Is it possible to write such a
> construct in your system?
>
Sure. It is possible and you can have a specialized allocator that does
something like chained stacks. But depending on your workload it may or may
not be as efficient as if you used fibers in the first place. Hence my
position is that you need both. Coroutines and Fibers. Neither of them is a
complete replacement of each other.
You mix and match according to what problems you are trying to solve.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_133_2002982252.1444614780637
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Sunday, October 11, 2015 at 6:08:47 PM UTC-7, Nicol=
Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div>It's simple: I want to take your stackless coroutine system and bu=
ild a stackful one out of it. I want a full-fledged fiber, which can cooper=
atively pause itself, allowing other processing to resume, and return to ex=
actly where it was. And it <i>does not matter</i> how many (awaiting) calls=
are between the pausing and the unpausing; I want resuming it to automatic=
ally resume the top-most function of the call stack.<br></div></div></block=
quote><div><br></div><div>Would basing this on real fibers (execution conte=
xt proposal by Nat and Oliver P0099) be better? There is a saying: Need a f=
iber, use a fiber :-) .</div><div>Nothing can really beat</div><div><br></d=
iv><div>ADD RSP,X and SUB RSP,X as a way to allocate, deallocate function f=
rame.</div><div><br></div><div>P0057 has cheaper suspend/resume and smaller=
memory footprint than P0099, but, if you need is a stack, building it out =
of (stackless) coroutines may not be the best idea. Real stack is really re=
ally efficient. You pay with memory and higher context switching cost, but =
the function call is dirt cheap.</div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div>I would hope that the goal w=
as to be something more than just a feature to make threading a bit easier.=
<br></div></div></blockquote><div><br></div><div>P0057 is not a thread repl=
acement, it is a callback replacement. It makes it easier to express asynch=
ronous state machine in the form of the imperative control flow.</div><div>=
<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v>So there would be some `coop_coroutine<T>` type which implements al=
l of the machinery needed for stackful coroutines. Is it possible to write =
such a construct in your system?<br></div></div></blockquote><div><br></div=
><div>Sure. It is possible and you can have a specialized allocator that do=
es something like chained stacks. But depending on your workload it may or =
may not be as efficient as if you used fibers in the first place. Hence my =
position is that you need both. Coroutines and Fibers. Neither of them is a=
complete replacement of each other.=C2=A0</div><div>You mix and match acco=
rding to what problems you are trying to solve.=C2=A0</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_133_2002982252.1444614780637--
------=_Part_132_1368539998.1444614780637--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 19:09:27 -0700 (PDT)
Raw View
------=_Part_140_1263431566.1444615767223
Content-Type: multipart/alternative;
boundary="----=_Part_141_945997962.1444615767224"
------=_Part_141_945997962.1444615767224
Content-Type: text/plain; charset=UTF-8
>
> P0057 is not a thread replacement, it is a callback replacement. It makes
> it easier to express asynchronous state machine in the form of the
> imperative control flow.
>
Let me expand this a little bit. P0057 supply syntactic sugar and a library
hookup that allows:
1) When using to solve async I/O problems, to express async state machine
as imperative control flow
2) When using it to produce lazily a sequence of values, to express sync
state machine as imperative control flow
3) If used with monadic types, helps to provide clean happy path and
automatic "exceptional" path propagation
4) We don't really know what uses other people will find. It is a little
bit like templates. I am not sure that Bjarne was thinking about computing
prime numbers at compile time when template were introduced, but people did
find creative use for them.
--
---
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_141_945997962.1444615767224
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>P0057 is not a thread replacement, it is a callback replacement. I=
t makes it easier to express asynchronous state machine in the form of the =
imperative control flow.</div></div></blockquote><div><br></div><div>Let me=
expand this a little bit. P0057 supply syntactic sugar and a library hooku=
p that allows:</div><div>1) When using to solve async I/O problems, to expr=
ess async state machine as imperative control flow</div><div>2) When using =
it to produce lazily a sequence of values, to express sync state machine as=
imperative control flow</div><div>3) If used with monadic types, helps to =
provide clean happy path and automatic "exceptional" path propaga=
tion</div><div>4) We don't really know what uses other people will find=
.. It is a little bit like templates. I am not sure that Bjarne was thinking=
about computing prime numbers at compile time when template were introduce=
d, but people did find creative use for them.</div><div><br></div><div><br>=
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_141_945997962.1444615767224--
------=_Part_140_1263431566.1444615767223--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 21:23:47 -0700 (PDT)
Raw View
------=_Part_3988_553386751.1444623827570
Content-Type: multipart/alternative;
boundary="----=_Part_3989_1287673189.1444623827571"
------=_Part_3989_1287673189.1444623827571
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 9:53:00 PM UTC-4, Gor Nishanov wrote:
>
>
> On Sunday, October 11, 2015 at 6:08:47 PM UTC-7, Nicol Bolas wrote:
>
I would hope that the goal was to be something more than just a feature to
>> make threading a bit easier.
>>
>
> P0057 is not a thread replacement, it is a callback replacement. It makes
> it easier to express asynchronous state machine in the form of the
> imperative control flow.
>
I don't know. I was just surprised by how much has been said about the
feature (I didn't know that stackful coroutines were still being pursued by
the committee until you mentioned P0099), yet it is just so... limited.
Highly useful, to be sure. But it just seems odd that the most limited and
restrictive "coroutine" proposal is the one that requires explicit language
support and has so many hooks, conditions, and so forth.
P0099 is just two things: a stack/executor, and a way to suspend/resume
(unfortunately, not asymmetrically. There's always something...). Simple,
to the point, and easily understood. P0057 says and does much more... just
to be able to hook a thread callback into half of a function's execution.
--
---
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_3989_1287673189.1444623827571
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Sunday, October 11, 2015 at 9:53:00 PM UTC-4, G=
or Nishanov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div><br>On =
Sunday, October 11, 2015 at 6:08:47 PM UTC-7, Nicol Bolas wrote: <br></div>=
</blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>I would hope =
that the goal was to be something more than just a feature to make threadin=
g a bit easier.<br></div></div></blockquote><div><br></div><div>P0057 is no=
t a thread replacement, it is a callback replacement. It makes it easier to=
express asynchronous state machine in the form of the imperative control f=
low.</div></div></blockquote><div><br>I don't know. I was just surprise=
d by how much has been said about the feature (I didn't know that stack=
ful coroutines were still being pursued by the committee until you mentione=
d P0099), yet it is just so... limited.<br><br>Highly useful, to be sure. B=
ut it just seems odd that the most limited and restrictive "coroutine&=
quot; proposal is the one that requires explicit language support and has s=
o many hooks, conditions, and so forth.<br><br>P0099 is just two things: a =
stack/executor, and a way to suspend/resume (unfortunately, not asymmetrica=
lly. There's always something...). Simple, to the point, and easily und=
erstood. P0057 says and does much more... just to be able to hook a thread =
callback into half of a function's execution.<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3989_1287673189.1444623827571--
------=_Part_3988_553386751.1444623827570--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 22:06:47 -0700 (PDT)
Raw View
------=_Part_215_1789472995.1444626407949
Content-Type: multipart/alternative;
boundary="----=_Part_216_1994394538.1444626407949"
------=_Part_216_1994394538.1444626407949
Content-Type: text/plain; charset=UTF-8
On Sunday, October 11, 2015 at 9:23:48 PM UTC-7, Nicol Bolas wrote:
>
> I don't know. I was just surprised by how much has been said about the
> feature (I didn't know that stackful coroutines were still being pursued by
> the committee until you mentioned P0099), yet it is just so... limited.
>
I am sorry you fill that way. :-)
Here is my view:
Thread
State: User-mode stack + kernel mode stack + context
Run by an OS scheduler
Unit of suspension: entire thread, CPU is free to run something else
Context: ~ entire register file +
Fiber (aka User-Mode-Scheduled-Thread, stackful coro)
State: User-mode stack + Context
Run by some thread
Unit of suspension: fiber, underlying thread is free to run
Context: ABI mandated non-volatile regs +
Coroutine (Stackless, aka Generalized Function)
State: Local variables + Context
Run by some thread or fiber
Unit of suspension: coroutine, underlying thread/fiber is free to run
Context: ~ 4 bytes +
Coroutine is strictly less powerful than a thread or a fiber. Either of
those can be used to emulate it, but, it has unmatched efficiency for the
problems it is good at solving:
The design goals for P0057 and its predecessors cannot be matched by thread
or fiber:
* Scalable (to billions of concurrent coroutines)
* Efficient (resume and suspend operations comparable in cost to a function
call overhead)
* Seamless interaction with existing facilities with no overhead
* Open ended coroutine machinery allowing library designers to develop
coroutine libraries exposing various high-level semantics, such as
generators, goroutines, tasks and more.
* Usable in environments where exception are forbidden or not available
All three abstractions I mentioned have their uses. You use appropriate
tool to solve the problem you have.
--
---
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_216_1994394538.1444626407949
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, October 11, 2015 at 9:23:48 PM UTC-7, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div=
>I don't know. I was just surprised by how much has been said about the=
feature (I didn't know that stackful coroutines were still being pursu=
ed by the committee until you mentioned P0099), yet it is just so... limite=
d.<br></div></div></blockquote><div><br></div><div>I am sorry you fill that=
way. :-)=C2=A0</div><div>Here is my view:</div><div><br></div><div>Thread<=
/div><div>=C2=A0 =C2=A0State: User-mode stack + kernel mode stack + context=
</div><div>=C2=A0 =C2=A0Run by an OS scheduler</div><div>=C2=A0 =C2=A0Unit =
of suspension: entire thread, CPU is free to run something else</div><div>=
=C2=A0 =C2=A0Context: ~ entire register file +</div><div><br></div><div>Fib=
er (aka User-Mode-Scheduled-Thread, stackful coro)</div><div>=C2=A0 =C2=A0S=
tate: User-mode stack + Context</div><div>=C2=A0 =C2=A0Run by some thread</=
div><div>=C2=A0 =C2=A0Unit of suspension: fiber, underlying thread is free =
to run</div><div>=C2=A0 =C2=A0Context: ABI mandated non-volatile regs +</di=
v><div><br></div><div>Coroutine (Stackless, aka Generalized Function)</div>=
<div>=C2=A0 =C2=A0State: Local variables + Context</div><div>=C2=A0 =C2=A0R=
un by some thread or fiber</div><div>=C2=A0 =C2=A0Unit of suspension: corou=
tine, underlying thread/fiber is free to run</div><div>=C2=A0 =C2=A0Context=
: ~ 4 bytes +</div><div>=C2=A0</div><div>Coroutine is strictly less powerfu=
l than a thread or a fiber. Either of those can =C2=A0be used to emulate it=
, but, it has unmatched efficiency for the problems it is good at solving:<=
/div><div><br></div><div>The design goals for P0057 and its predecessors ca=
nnot be matched by thread or fiber:</div><div><br></div><div><div>* Scalabl=
e (to billions of concurrent coroutines)</div><div>* Efficient (resume and =
suspend operations comparable in cost to a function call overhead)</div><di=
v>* Seamless interaction with existing facilities with no overhead</div><di=
v>* Open ended coroutine machinery allowing library designers to develop co=
routine libraries exposing various high-level semantics, such as generators=
, goroutines, tasks and more.</div><div>* Usable in environments where exce=
ption are forbidden or not available=C2=A0</div></div><div><br></div><div>A=
ll three abstractions I mentioned have their uses. You use appropriate tool=
to solve the problem you have.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_216_1994394538.1444626407949--
------=_Part_215_1789472995.1444626407949--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 22:07:16 -0700 (PDT)
Raw View
------=_Part_5032_1001350648.1444626436451
Content-Type: multipart/alternative;
boundary="----=_Part_5033_1491031199.1444626436452"
------=_Part_5033_1491031199.1444626436452
Content-Type: text/plain; charset=UTF-8
>
> I am sorry you fill that way. :-)
>
fill => feel
--
---
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_5033_1491031199.1444626436452
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>I am sor=
ry you fill that way. :-)=C2=A0</div></div></blockquote><div><br></div><div=
>fill =3D> feel=C2=A0</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5033_1491031199.1444626436452--
------=_Part_5032_1001350648.1444626436451--
.
Author: Evgeny Panasyuk <evgeny.panasyuk@gmail.com>
Date: Mon, 12 Oct 2015 09:02:19 +0300
Raw View
12.10.2015 8:06, Gor Nishanov:
> Here is my view:
>
> Thread
> State: User-mode stack + kernel mode stack + context
> Run by an OS scheduler
> Unit of suspension: entire thread, CPU is free to run something else
> Context: ~ entire register file +
>
> Fiber (aka User-Mode-Scheduled-Thread, stackful coro)
> State: User-mode stack + Context
> Run by some thread
> Unit of suspension: fiber, underlying thread is free to run
> Context: ABI mandated non-volatile regs +
>
> Coroutine (Stackless, aka Generalized Function)
> State: Local variables + Context
> Run by some thread or fiber
> Unit of suspension: coroutine, underlying thread/fiber is free to run
> Context: ~ 4 bytes +
> Coroutine is strictly less powerful than a thread or a fiber. Either of
> those can be used to emulate it, but, it has unmatched efficiency for
> the problems it is good at solving:
Actually stackless coroutines can be used to implement things which are
not possible (practically) for threads and fibers.
For instance:
* Generators which are Forward Iterators, not just single pass Input
Iterators.
* Implementation of List monad: small live demo
http://coliru.stacked-crooked.com/a/465f5bcb59c8b0b3
* Serialization of coroutine and even migration over network
For instance, this is possible with value-type stackless coroutines
proposed by Christopher Kohlhoff.
To some extent this approach can be implemented with current compilers
based on macros.
--
Evgeny Panasyuk
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Mon, 12 Oct 2015 09:50:25 +0200
Raw View
--047d7b6784263ca50f0521e39675
Content-Type: text/plain; charset=UTF-8
2015-10-12 3:08 GMT+02:00 Nicol Bolas <jmckesson@gmail.com>:
>
> So there would be some `coop_coroutine<T>` type which implements all of
> the machinery needed for stackful coroutines. Is it possible to write such
> a construct in your system?
>
proposed in N3985
--
---
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/.
--047d7b6784263ca50f0521e39675
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-12 3:08 GMT+02:00 Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:j=
mckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""></span><=
br><div>So there would be some `coop_coroutine<T>` type which impleme=
nts all of the machinery needed for stackful coroutines. Is it possible to =
write such a construct in your system?<br></div></div></blockquote></div><b=
r></div><div class=3D"gmail_extra">proposed in N3985<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b6784263ca50f0521e39675--
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Mon, 12 Oct 2015 09:58:20 +0200
Raw View
--089e01227efc8d44760521e3b28c
Content-Type: text/plain; charset=UTF-8
2015-10-12 6:23 GMT+02:00 Nicol Bolas <jmckesson@gmail.com>:
>
> P0099 is just two things: a stack/executor, and a way to suspend/resume
> (unfortunately, not asymmetrically. There's always something...). Simple,
> to the point, and easily understood. P0057 says and does much more... just
> to be able to hook a thread callback into half of a function's execution.
>
std::execution_context (N4397/N4398/P0099R0) is proposed as a low-level API
- used as a building-block for higher-level abstractions like (asymmetric)
coroutines and fiber (aka uer-land threads).
is uses symmetric context switching which is more efficient than the
asymmetric counterpart (prevents additional switch back).
asymmetric coroutines and fibers can be build upon this API as already
proved with boost.coroutine2 and boost.fiber.
in its essence a 'execution_context' is a pointer to a stack address, that
means if an execution_context gets suspended,
CPU registers (defined by the ABI) are pushed to the stack and the
execution_context stores the address of the last push-op.
if the context gets resumed, the address is assigned to the stack pointer
and the content of the registers is poped from the stack.
(at least that is how execution_context from boost.context works)
--
---
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/.
--089e01227efc8d44760521e3b28c
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-12 6:23 GMT+02:00 Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:j=
mckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span>:<b=
r><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:=
1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""></span><=
div><br>P0099 is just two things: a stack/executor, and a way to suspend/re=
sume (unfortunately, not asymmetrically. There's always something...). =
Simple, to the point, and easily understood. P0057 says and does much more.=
... just to be able to hook a thread callback into half of a function's =
execution.<br></div></div></blockquote></div><br></div><div class=3D"gmail_=
extra">std::execution_context (N4397/N4398/P0099R0) is proposed as a low-le=
vel API - used as a building-block for higher-level abstractions like (asym=
metric) coroutines and fiber (aka uer-land threads).<br></div><div class=3D=
"gmail_extra">is uses symmetric context switching which is more efficient t=
han the asymmetric counterpart (prevents additional switch back).<br></div>=
<div class=3D"gmail_extra">asymmetric coroutines and fibers can be build up=
on this API as already proved with boost.coroutine2 and boost.fiber.<br><br=
></div><div class=3D"gmail_extra">in its essence a 'execution_context&#=
39; is a pointer to a stack address, that means if an execution_context get=
s suspended,<br></div><div class=3D"gmail_extra">CPU registers (defined by =
the ABI) are pushed to the stack and the execution_context stores the addre=
ss of the last push-op.<br></div><div class=3D"gmail_extra">if the context =
gets resumed, the address is assigned to the stack pointer and the content =
of the registers is poped from the stack.<br></div><div class=3D"gmail_extr=
a">(at least that is how execution_context from boost.context works)<br></d=
iv></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e01227efc8d44760521e3b28c--
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Mon, 12 Oct 2015 10:03:22 +0200
Raw View
--089e0112cf108c10ff0521e3c4f3
Content-Type: text/plain; charset=UTF-8
2015-10-12 7:06 GMT+02:00 Gor Nishanov <gornishanov@gmail.com>:
>
> Fiber (aka User-Mode-Scheduled-Thread, stackful coro)
> State: User-mode stack + Context
> Run by some thread
> Unit of suspension: fiber, underlying thread is free to run
> Context: ABI mandated non-volatile regs +
>
+ user-land scheduler
> Coroutine (Stackless, aka Generalized Function)
> State: Local variables + Context
> Run by some thread or fiber
> Unit of suspension: coroutine, underlying thread/fiber is free to run
> Context: ~ 4 bytes +
>
== stackless Coroutine (allocation of activation record/frame for each
instance)
+ stackful Coroutines
> The design goals for P0057 and its predecessors cannot be matched by
> thread or fiber:
>
> * Scalable (to billions of concurrent coroutines)
> * Efficient (resume and suspend operations comparable in cost to a
> function call overhead)
> * Seamless interaction with existing facilities with no overhead
> * Open ended coroutine machinery allowing library designers to develop
> coroutine libraries exposing various high-level semantics, such as
> generators, goroutines, tasks and more.
> * Usable in environments where exception are forbidden or not available
>
--
---
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/.
--089e0112cf108c10ff0521e3c4f3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-12 7:06 GMT+02:00 Gor Nishanov <span dir=3D"ltr"><<a href=3D"mailto:=
gornishanov@gmail.com" target=3D"_blank">gornishanov@gmail.com</a>></spa=
n>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D""></s=
pan><div><br></div><div>Fiber (aka User-Mode-Scheduled-Thread, stackful cor=
o)</div><div>=C2=A0 =C2=A0State: User-mode stack + Context</div><div>=C2=A0=
=C2=A0Run by some thread</div><div>=C2=A0 =C2=A0Unit of suspension: fiber,=
underlying thread is free to run</div><div>=C2=A0 =C2=A0Context: ABI manda=
ted non-volatile regs +</div></div></blockquote><div><br></div><div>+ user-=
land scheduler<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><div></div><div>Coroutine (Stackless, aka Generalized Functio=
n)</div><div>=C2=A0 =C2=A0State: Local variables + Context</div><div>=C2=A0=
=C2=A0Run by some thread or fiber</div><div>=C2=A0 =C2=A0Unit of suspensio=
n: coroutine, underlying thread/fiber is free to run</div><div>=C2=A0 =C2=
=A0Context: ~ 4 bytes +</div></div></blockquote><div><br></div><div>=3D=3D =
stackless Coroutine (allocation of activation record/frame for each instanc=
e) <br></div><div><br></div><div>+ stackful Coroutines<br></div><div>=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div></div=
><div>The design goals for P0057 and its predecessors cannot be matched by =
thread or fiber:</div><div><br></div><div><div>* Scalable (to billions of c=
oncurrent coroutines)</div><div>* Efficient (resume and suspend operations =
comparable in cost to a function call overhead)</div><div>* Seamless intera=
ction with existing facilities with no overhead</div><div>* Open ended coro=
utine machinery allowing library designers to develop coroutine libraries e=
xposing various high-level semantics, such as generators, goroutines, tasks=
and more.</div><div>* Usable in environments where exception are forbidden=
or not available</div></div></div></blockquote><div><br>=C2=A0</div></div>=
<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0112cf108c10ff0521e3c4f3--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 02:20:48 -0700 (PDT)
Raw View
------=_Part_4291_1930568880.1444641648199
Content-Type: multipart/alternative;
boundary="----=_Part_4292_1752773993.1444641648200"
------=_Part_4292_1752773993.1444641648200
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 6:06:48 AM UTC+1, Gor Nishanov wrote:
>
> On Sunday, October 11, 2015 at 9:23:48 PM UTC-7, Nicol Bolas wrote:
>>
>> I don't know. I was just surprised by how much has been said about the
>> feature (I didn't know that stackful coroutines were still being pursued by
>> the committee until you mentioned P0099), yet it is just so... limited.
>>
>
> I am sorry you fill that way. :-)
> Here is my view:
>
> Thread
> State: User-mode stack + kernel mode stack + context
> Run by an OS scheduler
> Unit of suspension: entire thread, CPU is free to run something else
> Context: ~ entire register file +
>
> Fiber (aka User-Mode-Scheduled-Thread, stackful coro)
> State: User-mode stack + Context
> Run by some thread
> Unit of suspension: fiber, underlying thread is free to run
> Context: ABI mandated non-volatile regs +
>
> Coroutine (Stackless, aka Generalized Function)
> State: Local variables + Context
> Run by some thread or fiber
> Unit of suspension: coroutine, underlying thread/fiber is free to run
> Context: ~ 4 bytes +
>
Please, let's not co-opt terms. Coroutine is really the generic concept.
When used unqualified it historically referred to stackful, usually
asymmetric, coroutines (lua, icon, boost, the original invention from
Conway. Historically fibers are just symmetric stackful coroutines. In the
last decade or two, 'generator' is the term that has been used most often
to refer to asymmetric stackless coroutines.
>
> Coroutine is strictly less powerful than a thread or a fiber. Either of
> those can be used to emulate it, but, it has unmatched efficiency for the
> problems it is good at solving:
>
I assume you mean Generator here.
>
> The design goals for P0057 and its predecessors cannot be matched by
> thread or fiber:
>
> * Scalable (to billions of concurrent coroutines)
>
I agree it is hard to match the efficiency of only allocating a frame
instead of a full stack, but with compiler support for full coroutines,
this could be matched.
> * Efficient (resume and suspend operations comparable in cost to a
> function call overhead)
>
that's already the case for an optimized implementation of stackful
coroutines. The win with generators is that they would allow direct
inlining of the callee into the caller.
> * Seamless interaction with existing facilities with no overhead
>
that's actually a feature of stackful coroutines. Most common
implementations of stackless coroutines lead to the red or blue function
problem:
http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/.
> * Open ended coroutine machinery allowing library designers to develop
> coroutine libraries exposing various high-level semantics, such as
> generators, goroutines, tasks and more.
>
goroutines are stackful. They are trivially emulable on top of fibers, not
so much on top of stackless generators.
> * Usable in environments where exception are forbidden or not available
>
>
How is that an advantage of stackles over stackful coroutines?
> All three abstractions I mentioned have their uses. You use appropriate
> tool to solve the problem you have.
>
It would be better to only have an abstraction: stackful symmetric
coroutines with compiler support for eliding the side stack if all yield
points are lexically contained in the function at the bottom of the ideal
stack.
-- gpd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4292_1752773993.1444641648200
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 6:06:48 AM UTC+1, Gor Nishanov wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">On Sunday, October 1=
1, 2015 at 9:23:48 PM UTC-7, Nicol Bolas wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>I don't know. I was just surprised by=
how much has been said about the feature (I didn't know that stackful =
coroutines were still being pursued by the committee until you mentioned P0=
099), yet it is just so... limited.<br></div></div></blockquote><div><br></=
div><div>I am sorry you fill that way. :-)=C2=A0</div><div>Here is my view:=
</div><div><br></div><div>Thread</div><div>=C2=A0 =C2=A0State: User-mode st=
ack + kernel mode stack + context</div><div>=C2=A0 =C2=A0Run by an OS sched=
uler</div><div>=C2=A0 =C2=A0Unit of suspension: entire thread, CPU is free =
to run something else</div><div>=C2=A0 =C2=A0Context: ~ entire register fil=
e +</div><div><br></div><div>Fiber (aka User-Mode-Scheduled-Thread, stackfu=
l coro)</div><div>=C2=A0 =C2=A0State: User-mode stack + Context</div><div>=
=C2=A0 =C2=A0Run by some thread</div><div>=C2=A0 =C2=A0Unit of suspension: =
fiber, underlying thread is free to run</div><div>=C2=A0 =C2=A0Context: ABI=
mandated non-volatile regs +</div><div><br></div><div>Coroutine (Stackless=
, aka Generalized Function)</div><div>=C2=A0 =C2=A0State: Local variables +=
Context</div><div>=C2=A0 =C2=A0Run by some thread or fiber</div><div>=C2=
=A0 =C2=A0Unit of suspension: coroutine, underlying thread/fiber is free to=
run</div><div>=C2=A0 =C2=A0Context: ~ 4 bytes +</div></div></blockquote><d=
iv><br>Please, let's not co-opt terms. Coroutine is really the generic =
concept. When used unqualified it historically referred to stackful, usuall=
y asymmetric, coroutines (lua, icon, boost, the original invention from Con=
way. Historically fibers are just symmetric stackful coroutines. In the las=
t decade or two, 'generator' is the term that has been used most of=
ten to refer to asymmetric stackless coroutines.<br>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=C2=A0</div><div>Co=
routine is strictly less powerful than a thread or a fiber. Either of those=
can =C2=A0be used to emulate it, but, it has unmatched efficiency for the =
problems it is good at solving:</div></div></blockquote><div><br>I assume y=
ou mean Generator here.<br>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div><br></div><div>The design goals for P0057 an=
d its predecessors cannot be matched by thread or fiber:</div><div><br></di=
v><div><div>* Scalable (to billions of concurrent coroutines)</div></div></=
div></blockquote><div><br>I agree it is hard to match the efficiency of onl=
y allocating a frame instead of a full stack, but with compiler support for=
full coroutines, this could be matched.<br>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div>* Efficient (resume =
and suspend operations comparable in cost to a function call overhead)</div=
></div></div></blockquote><div><br>that's already the case for an optim=
ized implementation of stackful coroutines. The win with generators is that=
they would allow direct inlining of the callee into the caller.<br>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><di=
v>* Seamless interaction with existing facilities with no overhead</div></d=
iv></div></blockquote><div><br>that's actually a feature of stackful co=
routines. Most common implementations of stackless coroutines lead to the r=
ed or blue function problem: http://journal.stuffwithstuff.com/2015/02/01/w=
hat-color-is-your-function/.<br>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div><div>* Open ended coroutine machinery a=
llowing library designers to develop coroutine libraries exposing various h=
igh-level semantics, such as generators, goroutines, tasks and more.</div><=
/div></div></blockquote><div><br>goroutines are stackful. They are triviall=
y emulable on top of fibers, not so much on top of stackless generators.<br=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div><div>* Usable in environments where exception are forbidden or not ava=
ilable=C2=A0</div></div><div><br></div></div></blockquote><div><br>How is t=
hat an advantage of stackles over stackful coroutines?<br>=C2=A0</div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div>Al=
l three abstractions I mentioned have their uses. You use appropriate tool =
to solve the problem you have.</div></div></blockquote><div><br>It would be=
better to only have an abstraction: stackful symmetric coroutines with com=
piler support for eliding the side stack if all yield points are lexically =
contained in the function at the bottom of the ideal stack.<br><br>-- gpd<b=
r>=C2=A0</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4292_1752773993.1444641648200--
------=_Part_4291_1930568880.1444641648199--
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Mon, 12 Oct 2015 12:04:25 +0200
Raw View
--001a1140980e6ece530521e57543
Content-Type: text/plain; charset=UTF-8
2015-10-12 11:20 GMT+02:00 Giovanni Piero Deretta <gpderetta@gmail.com>:
It would be better to only have an abstraction: stackful symmetric
> coroutines with compiler support for eliding the side stack if all yield
> points are lexically contained in the function at the bottom of the ideal
> stack.
>
+1
--
---
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/.
--001a1140980e6ece530521e57543
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2015=
-10-12 11:20 GMT+02:00 Giovanni Piero Deretta <span dir=3D"ltr"><<a href=
=3D"mailto:gpderetta@gmail.com" target=3D"_blank">gpderetta@gmail.com</a>&g=
t;</span>:<br><br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .=
8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=3D""></span>It=
would be better to only have an abstraction: stackful symmetric coroutines=
with compiler support for eliding the side stack if all yield points are l=
exically contained in the function at the bottom of the ideal stack.<br></b=
lockquote></div><br>+1<br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1140980e6ece530521e57543--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 03:43:36 -0700 (PDT)
Raw View
------=_Part_150_1641613242.1444646616988
Content-Type: multipart/alternative;
boundary="----=_Part_151_1908102828.1444646616989"
------=_Part_151_1908102828.1444646616989
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 11:04:46 AM UTC+1, Oliver Kowalke wrote:
>
> 2015-10-12 11:20 GMT+02:00 Giovanni Piero Deretta <gpde...@gmail.com
> <javascript:>>:
>
> It would be better to only have an abstraction: stackful symmetric
>> coroutines with compiler support for eliding the side stack if all yield
>> points are lexically contained in the function at the bottom of the ideal
>> stack.
>>
>
> +1
>
And BTW, I think this is pretty much the same analysis that is required to
elide the memory allocation of the generator frame required by the current
stackless coroutine proposal. The possible optimizations are like the
following:
A) in the callee, if the caller continuation does not escape, the callee
stack can be elided. Only the stack frame need to be explicitly allocated:
the caller stack can be reused for any sub routine call as we know that the
caller won't be possibly resumed as the callee control its continuation.
B) additionally, in the caller, if the callee continuation also doesn't
escape, we can stack allocate the callee stack frame instead of heap
allocating it as its lifetime can be determined statically.
We can't profitably do B if we can't do A, because we would need to
allocate a whole stack instead of just one frame inside the caller stack.
Note that 'Escape' means that the compiler is not able to statically track
all pointers to the continuation. This means that it would still possible
for the compiler to do the 'stackless' optimization even if, on the callee
side, the continuation is passed to a sub routine and yielded from there,
as long as the compiler can 'see' inside the subroutine (via inlining or
interprocedural analysis).
As it is desirable to be able to statically verify the stackless property,
a set of optional annotations can be added to annotate both continuations
and functions. Passing a continuation to an annotated function guarantee
that this action by itself won't make the continuation escaped. Annotated
functions must of course be inline. Annotating a continuation prevent its
address to be taken and prevents passing it to non annotated functions.
Note that the annotations can be used for either (or both) guaranteeing the
stackless property (by annotating the caller continuation in the callee)
and the freedom from allocation (by annotating the callee continuation in
the caller).
-- gpd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_151_1908102828.1444646616989
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, October 12, 2015 at 11:04:46 AM UTC+1, =
Oliver Kowalke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div class=3D"gmail_quote">2015-10-12 11:20 GMT+02:00 Giovann=
i Piero Deretta <span dir=3D"ltr"><<a href=3D"javascript:" target=3D"_bl=
ank" gdf-obfuscated-mailto=3D"ZMcEIyjtDQAJ" rel=3D"nofollow" onmousedown=3D=
"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
9;javascript:';return true;">gpde...@gmail.com</a>></span>:<br><br><=
blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px=
#ccc solid;padding-left:1ex"><span></span>It would be better to only have =
an abstraction: stackful symmetric coroutines with compiler support for eli=
ding the side stack if all yield points are lexically contained in the func=
tion at the bottom of the ideal stack.<br></blockquote></div><br>+1<br></di=
v></div></blockquote><div><br>And BTW, I think this is pretty much the same=
analysis that is required to elide the memory allocation of the generator =
frame required by the current stackless coroutine proposal. The possible op=
timizations are like the following:<br><br>A) in the callee, if the caller =
continuation does not escape, the callee stack can be elided. Only the stac=
k frame need to be explicitly allocated: the caller stack can be reused for=
any sub routine call as we know that the caller won't be possibly resu=
med as the callee control its continuation.<br>B) additionally, in the call=
er, if the callee continuation also doesn't escape, we can stack alloca=
te the callee stack frame instead of heap allocating it as its lifetime can=
be determined statically.<br><br>We can't profitably do B if we can=
9;t do A, because we would need to allocate a whole stack instead of just o=
ne frame inside the caller stack.<br><br>Note that 'Escape' means t=
hat the compiler is not able to statically track all pointers to the contin=
uation. This means that it would still possible for the compiler to do the =
'stackless' optimization even if, on the callee side, the continuat=
ion is passed to a sub routine and yielded from there, as long as the compi=
ler can 'see' inside the subroutine (via inlining or interprocedura=
l analysis).<br><br>As it is desirable to be able to statically verify the =
stackless property, a set of optional annotations can be added to annotate =
both continuations and functions. Passing a continuation to an annotated fu=
nction guarantee that this action by itself won't make the continuation=
escaped. Annotated functions must of course be inline. Annotating a contin=
uation prevent its address to be taken and prevents passing it to non annot=
ated functions. <br><br>Note that the annotations can be used for either (o=
r both) guaranteeing the stackless property (by annotating the caller conti=
nuation in the callee) and the freedom from allocation (by annotating the c=
allee continuation in the caller).<br><br>-- gpd<br><br><br><br><br></div><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_151_1908102828.1444646616989--
------=_Part_150_1641613242.1444646616988--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 05:24:56 -0700 (PDT)
Raw View
------=_Part_5742_114142388.1444652696783
Content-Type: multipart/alternative;
boundary="----=_Part_5743_1057058812.1444652696783"
------=_Part_5743_1057058812.1444652696783
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 2:20:48 AM UTC-7, Giovanni Piero Deretta
wrote:
>
> Please, let's not co-opt terms. Coroutine is really the generic concept.
> When used unqualified it historically referred to stackful, usually
> asymmetric, coroutines (lua, icon, boost, the original invention from
> Conway. Historically fibers are just symmetric stackful coroutines. In the
> last decade or two, 'generator' is the term that has been used most often
> to refer to asymmetric stackless coroutines.
>
I fully agree. Let's not co-opt terms and go with historical definitions.
Historically (going back to the end of 50s), coroutines meant a generalized
subroutine, or as Knuth defines a subroutine is special-case of a
coroutine. Nowhere there was a discussion that subroutines and coroutines
must carry a call stack around with them.
The term was corrupted afterwards as the frequently used emulation of
coroutines was done via manipulating stacks of the currently running
thread/process. Hence the mix-up between coroutines and light-weight
threads.
The term fiber was first appeared in NT4 (end of 90s) with the OS facility
that provided user-mode stack manipulation APIs that allowed implementing
cooperative multitasking. Scheduler was not part of the fiber APIs. It had
facilities with which you can implement a scheduler. By that historical
definition Oliver's execution_context is a fiber.
I like this terminology not necessarily because it is historically
accurate, but, because it give short, crisp memorable words to orthogonal
concepts without the need to disambiguate with various adjectives.
Thread? which one, heavy-weight one or light-weight one like fiber?
Fiber?, do you mean like in NT (no scheduler included), or as the one
proposed to Boost that does include the scheduler?
Coroutine?, do you mean stackful (meaning either a fiber or coroutine
emulation via fiber) or stackless and if stackless, do you mean like Python
stackless (meaning does not use OS stack or stackless stackless where there
is no stack of any kind? or Python async function and generator which are
stackless stackless coroutines?)
That mess needs to be cleaned up. Thus, the set of definitions I use.
--
---
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_5743_1057058812.1444652696783
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, October 12, 2015 at 2:20:48 AM UTC-7, G=
iovanni Piero Deretta wrote:<blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Pl=
ease, let's not co-opt terms. Coroutine is really the generic concept. =
When used unqualified it historically referred to stackful, usually asymmet=
ric, coroutines (lua, icon, boost, the original invention from Conway. Hist=
orically fibers are just symmetric stackful coroutines. In the last decade =
or two, 'generator' is the term that has been used most often to re=
fer to asymmetric stackless coroutines.<br></blockquote><div><br></div><div=
>I fully agree. Let's not co-opt terms and go with historical definitio=
ns.</div><div><br></div><div>Historically (going back to the end of 50s), c=
oroutines meant a generalized subroutine, or as Knuth defines a subroutine =
is special-case of a coroutine. Nowhere there was a discussion that subrout=
ines and coroutines must carry a call stack around with them.=C2=A0</div><d=
iv><br></div><div>The term was corrupted afterwards as the frequently used =
emulation of coroutines was done via manipulating stacks of the currently r=
unning thread/process. Hence the mix-up between coroutines and light-weight=
threads.</div><div><br></div><div>The term fiber was first appeared in NT4=
(end of 90s) with the OS facility that provided user-mode stack manipulati=
on APIs that allowed implementing cooperative multitasking. Scheduler was n=
ot part of the fiber APIs. It had facilities with which you can implement a=
scheduler. By that historical definition Oliver's execution_context is=
a fiber.</div><div><br></div><div>I like this terminology not necessarily =
because it is historically accurate, but, because it give short, crisp memo=
rable words to orthogonal concepts without the need to disambiguate with va=
rious adjectives.</div><div><br></div><div>Thread? which one, heavy-weight =
one or light-weight one like fiber?</div><div>Fiber?, do you mean like in N=
T (no scheduler included), or as the one proposed to Boost that does includ=
e the scheduler?</div><div>Coroutine?, do you mean stackful (meaning either=
a fiber or coroutine emulation via fiber) or stackless and if stackless, d=
o you mean like Python stackless (meaning does not use OS stack or stackles=
s stackless where there is no stack of any kind? or Python async function a=
nd generator which are stackless stackless coroutines?)</div><div><br></div=
><div>That mess needs to be cleaned up. Thus, the set of definitions I use.=
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5743_1057058812.1444652696783--
------=_Part_5742_114142388.1444652696783--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 05:52:06 -0700 (PDT)
Raw View
------=_Part_26_79166956.1444654327019
Content-Type: multipart/alternative;
boundary="----=_Part_27_84565899.1444654327019"
------=_Part_27_84565899.1444654327019
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 1:24:56 PM UTC+1, Gor Nishanov wrote:
>
>
>
> On Monday, October 12, 2015 at 2:20:48 AM UTC-7, Giovanni Piero Deretta=
=20
> wrote:
>>
>> Please, let's not co-opt terms. Coroutine is really the generic concept.=
=20
>> When used unqualified it historically referred to stackful, usually=20
>> asymmetric, coroutines (lua, icon, boost, the original invention from=20
>> Conway. Historically fibers are just symmetric stackful coroutines. In t=
he=20
>> last decade or two, 'generator' is the term that has been used most ofte=
n=20
>> to refer to asymmetric stackless coroutines.
>>
>
> I fully agree. Let's not co-opt terms and go with historical definitions.
>
> Historically (going back to the end of 50s), coroutines meant a=20
> generalized subroutine, or as Knuth defines a subroutine is special-case =
of=20
> a coroutine. Nowhere there was a discussion that subroutines and coroutin=
es=20
> must carry a call stack around with them.=20
>
> The term was corrupted afterwards as the frequently used emulation of=20
> coroutines was done via manipulating stacks of the currently running=20
> thread/process. Hence the mix-up between coroutines and light-weight=20
> threads.
>
>
The call stack as a concept exist distinctly from its actual physical=20
realization; similarly the 'stackful/stackless' terms have nothing to do=20
with the classic physical C stack. A language implementation that heap=20
allocates each individual function frame and has call/cc can trivially=20
implement stackful coroutines even if it has nothing like the C stack (for=
=20
example stackless python or many scheme interpreters). The terms simply=20
refer to the ability to yield from a nested call, which was a property of=
=20
coroutines as originally defined or otherwise they wouldn't have been a=20
generalization of subroutines.=20
The terms stackful and stackless come from "Revisiting Coroutines" by Ana L=
=20
=CC=81cia de Moura and Roberto Ierusalimschy", which is pretty much the=20
definitive treatment of the topic. I believe I introduced these definitions=
=20
to the C++ community when I used them in the original Boost.Coroutine GSOC=
=20
in 2006 as that paper had a huge influence in my design.=20
-- gpd
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_27_84565899.1444654327019
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, October 12, 2015 at 1:24:56 PM UTC+1, Gor Nishanov wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><br>On M=
onday, October 12, 2015 at 2:20:48 AM UTC-7, Giovanni Piero Deretta wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border=
-left:1px #ccc solid;padding-left:1ex">Please, let's not co-opt terms. =
Coroutine is really the generic concept. When used unqualified it historica=
lly referred to stackful, usually asymmetric, coroutines (lua, icon, boost,=
the original invention from Conway. Historically fibers are just symmetric=
stackful coroutines. In the last decade or two, 'generator' is the=
term that has been used most often to refer to asymmetric stackless corout=
ines.<br></blockquote><div><br></div><div>I fully agree. Let's not co-o=
pt terms and go with historical definitions.</div><div><br></div><div>Histo=
rically (going back to the end of 50s), coroutines meant a generalized subr=
outine, or as Knuth defines a subroutine is special-case of a coroutine. No=
where there was a discussion that subroutines and coroutines must carry a c=
all stack around with them.=C2=A0</div><div><br></div><div>The term was cor=
rupted afterwards as the frequently used emulation of coroutines was done v=
ia manipulating stacks of the currently running thread/process. Hence the m=
ix-up between coroutines and light-weight threads.</div><div><br></div></di=
v></blockquote><div><br>The call stack as a concept exist distinctly from i=
ts actual physical realization; similarly the 'stackful/stackless' =
terms have nothing to do with the classic physical C stack. A language impl=
ementation that heap allocates each individual function=20
frame and has call/cc can trivially implement stackful coroutines even if i=
t has=20
nothing like the C stack (for example stackless python or many scheme inter=
preters). The terms simply refer to the ability to yield from a nested call=
, which was a property of coroutines as originally defined or otherwise the=
y wouldn't have been a generalization of subroutines. <br><br>The terms=
stackful and stackless come from "Revisiting Coroutines" by Ana =
L =CC=81cia de Moura and Roberto Ierusalimschy", which is pretty much =
the definitive treatment of the topic. I believe I introduced these definit=
ions to the C++ community when I used them in the original Boost.Coroutine =
GSOC in 2006 as that paper had a huge influence in my design. <br><br>-- gp=
d<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_27_84565899.1444654327019--
------=_Part_26_79166956.1444654327019--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 06:17:05 -0700 (PDT)
Raw View
------=_Part_5538_1810739136.1444655825571
Content-Type: multipart/alternative;
boundary="----=_Part_5539_235170393.1444655825572"
------=_Part_5539_235170393.1444655825572
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 5:52:07 AM UTC-7, Giovanni Piero Deretta=20
wrote:
>
> The terms stackful and stackless come from "Revisiting Coroutines" by Ana=
=20
> L =CC=81cia de Moura and Roberto Ierusalimschy", which is pretty much the=
=20
> definitive treatment of the topic.=20
>
I am well aware of this paper. They surveyed the messy field and tried try=
=20
to clean up the existing terminology mess. They were tame in their attempts=
=20
to clean up the terminology and went with "let's pile up more adjectives=20
path". The conclusion is questionable too. They came to the conclusion that=
=20
(in their terminology) stackful asymmetric coroutine are the best.
Well they sacrificed performance on two fronts.
If they want stackfullness, they should have chosen fibers. Context switch=
=20
is expensive in the fiber, thus you want to minimize number of switches you=
=20
do. Going with asymmetric, they doubled the cost, since now when we want to=
=20
do direct transfer between two fibers, we have to first go back to the=20
scheduler.
And, of course, by favoring "stackfulness" they left a lot of performance=
=20
on the floor.
We control the language we use in C++. Whatever terms we chose can=20
influence the rest of the industry.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_5539_235170393.1444655825572
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Monday, October 12, 2015 at 5:52:07 AM UTC-7, Giova=
nni Piero Deretta wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>T=
he terms stackful and stackless come from "Revisiting Coroutines"=
by Ana L =CC=81cia de Moura and Roberto Ierusalimschy", which is pret=
ty much the definitive treatment of the topic. </div></blockquote><div><br>=
</div><div>I am well aware of this paper. They surveyed the messy field and=
tried try to clean up the existing terminology mess. They were tame in the=
ir attempts to clean up the terminology and went with "let's pile =
up more adjectives path". The conclusion is questionable too. They cam=
e to the conclusion that (in their terminology) stackful asymmetric corouti=
ne are the best.</div><div><br></div><div>Well they sacrificed performance =
on two fronts.</div><div><br></div><div>If they want stackfullness, they sh=
ould have chosen fibers. Context switch is expensive in the fiber, thus you=
want to minimize number of switches you do. Going with asymmetric, they do=
ubled the cost, since now when we want to do direct transfer between two fi=
bers, we have to first go back to the scheduler.</div><div><br></div><div>A=
nd, of course, by favoring "stackfulness" they left a lot of perf=
ormance on the floor.</div><div><br></div><div>We control the language we u=
se in C++. Whatever terms we chose can influence the rest of the industry.<=
/div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5539_235170393.1444655825572--
------=_Part_5538_1810739136.1444655825571--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Mon, 12 Oct 2015 06:25:51 -0700 (PDT)
Raw View
------=_Part_5845_1116118573.1444656351988
Content-Type: multipart/alternative;
boundary="----=_Part_5846_1109739884.1444656351989"
------=_Part_5846_1109739884.1444656351989
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hi Gor,
Is there noexcept requirement on initial_suspend/final_suspend?
Quoting from P0057R0, 8.4.4/5:
the coroutine behaves as if its body were:
> {
> P p;
> await-keyword p.initial_suspend(); // initial suspend point
> F=E2=80=99
> await-keyword p.final_suspend(); // final suspend point
> }
> where local variable p is defined for exposition only and F=E2=80=99 is F=
if P=20
> does not define a set_-
> exception member function, and
> try { F } catch(...) { p .set_exception(std::current_exception()); }
> otherwise.
And there are 2 ways to call the coroutine: 1) `operator()` and 2)=20
`resume`, where the former is noexcept and the latter can throw.
In the above definition, `initial_suspend` is not surrounded in the=20
try-block, does that mean if it throws, when called by `operator()` the=20
program will terminate?
and when called by `resume`, will it bypass final_suspend? will it reclaim=
=20
the coroutine-frame?
final_suspend is similar, but I believe it should be noexcept. If it=20
throws, when called by `operator()`, the program will terminate anyway; whe=
n=20
called by `resume`, you can't decide whether to suspend it or not.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_5846_1109739884.1444656351989
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div style=3D"font-family: arial, sans-serif; font-size: s=
mall;">Hi Gor,</div><div style=3D"font-family: arial, sans-serif; font-size=
: small;"><br></div><span style=3D"font-family: arial, sans-serif; font-siz=
e: small;">Is there noexcept requirement on initial_suspend/final_suspend?<=
/span><div style=3D"font-family: arial, sans-serif; font-size: small;"><br>=
</div><div style=3D"font-family: arial, sans-serif; font-size: small;">Quot=
ing from P0057R0,=C2=A08.4.4/5:</div><div style=3D"font-family: arial, sans=
-serif; font-size: small;"><br></div><div><blockquote style=3D"margin: 0px =
0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204=
); border-left-style: solid; padding-left: 1ex;" class=3D"gmail_quote">the =
coroutine behaves as if its body were:<br><div class=3D"prettyprint" style=
=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break-word; background=
-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subp=
rettyprint"><span style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 P p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 await</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">-</span><span style=3D"color: #000;" class=3D"styled-by-prettify">keyword=
p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">initial_suspend</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// initial suspend point</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 F</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=E2=
=80=99</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 =C2=A0 await</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">-</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
keyword p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">final_susp=
end</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #800;" class=3D"styled-by-prettify">// final suspend point<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></c=
ode></div><font face=3D"arial, sans-serif" size=3D"2">where local variable =
p is defined for exposition only and F=E2=80=99 is F if P does not define a=
set_-<br></font><font face=3D"arial, sans-serif" size=3D"2">exception memb=
er function, and<br></font><div class=3D"prettyprint" style=3D"border: 1px =
solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb(250,=
250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">try</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> F </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">catch</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(...)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> p </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">set_exception</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">current_exception</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">());</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">}</span></div></code></div><font face=3D"arial, sans-serif" size=
=3D"2">otherwise.</font></blockquote><div><br></div><div>=C2=A0And there ar=
e 2 ways to call the coroutine: 1) `operator()` and 2) `resume`, where the =
former is noexcept and the latter can throw.</div><div><br></div><div>In th=
e above definition, `<span style=3D"font-family: arial, sans-serif; font-si=
ze: small;">initial_suspend` is not surrounded in the try-block, does that =
mean if it throws, when called by `</span>operator()<span style=3D"font-fam=
ily: arial, sans-serif; font-size: small;">` the program will terminate?</s=
pan></div><div><span style=3D"font-size: small; font-family: arial, sans-se=
rif;">and when called by `</span>resume<span style=3D"font-size: small; fon=
t-family: arial, sans-serif;">`, will it bypass=C2=A0</span><span style=3D"=
font-family: arial, sans-serif; font-size: small;">final_suspend? will it r=
eclaim the coroutine-frame?</span><br></div><div><span style=3D"font-family=
: arial, sans-serif; font-size: small;"><br></span></div><div><span style=
=3D"font-family: arial, sans-serif; font-size: small;">final_suspend is sim=
ilar, but I believe it should be=C2=A0</span>noexcept. If it throws, when<s=
pan style=3D"font-size: small; font-family: arial, sans-serif;">=C2=A0calle=
d by `</span>operator()<span style=3D"font-size: small; font-family: arial,=
sans-serif;">`,</span><span style=3D"font-family: arial, sans-serif; font-=
size: small;">=C2=A0the program will terminate</span>=C2=A0anyway;=C2=A0<sp=
an style=3D"font-size: small; font-family: arial, sans-serif;">when called =
by `</span>resume<span style=3D"font-size: small; font-family: arial, sans-=
serif;">`, you can't decide whether to suspend it or not.</span></div><=
div style=3D"font-family: arial, sans-serif; font-size: small;"><br></div><=
/div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5846_1109739884.1444656351989--
------=_Part_5845_1116118573.1444656351988--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 06:37:53 -0700 (PDT)
Raw View
------=_Part_436_81250470.1444657073640
Content-Type: multipart/alternative;
boundary="----=_Part_437_1109794321.1444657073640"
------=_Part_437_1109794321.1444657073640
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 2:17:05 PM UTC+1, Gor Nishanov wrote:
>
>
> On Monday, October 12, 2015 at 5:52:07 AM UTC-7, Giovanni Piero Deretta=
=20
> wrote:
>>
>> The terms stackful and stackless come from "Revisiting Coroutines" by An=
a=20
>> L =CC=81cia de Moura and Roberto Ierusalimschy", which is pretty much th=
e=20
>> definitive treatment of the topic.=20
>>
>
> I am well aware of this paper. They surveyed the messy field and tried tr=
y=20
> to clean up the existing terminology mess. They were tame in their attemp=
ts=20
> to clean up the terminology and went with "let's pile up more adjectives=
=20
> path". The conclusion is questionable too. They came to the conclusion th=
at=20
> (in their terminology) stackful asymmetric coroutine are the best.
>
> Well they sacrificed performance on two fronts.
>
> If they want stackfullness, they should have chosen fibers. Context switc=
h=20
> is expensive in the fiber, thus you want to minimize number of switches y=
ou=20
> do. Going with asymmetric, they doubled the cost, since now when we want =
to=20
> do direct transfer between two fibers, we have to first go back to the=20
> scheduler.
>
agree about this; I believe that symmetric coroutines are better.
=20
>
> And, of course, by favoring "stackfulness" they left a lot of performance=
=20
> on the floor.
>
.... but of course disagree about this. As I discussed previously, I believe=
=20
that the stackless coroutines can be implemented as a compiler optimization=
=20
on top of stackful coroutines; the loss of expressiveness is otherwise too=
=20
great.=20
-- gpd
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_437_1109794321.1444657073640
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 2:17:05 PM UTC+1, Gor Nishanov wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>On Monday, Octob=
er 12, 2015 at 5:52:07 AM UTC-7, Giovanni Piero Deretta wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div>The terms stackful and stackless come from =
"Revisiting Coroutines" by Ana L =CC=81cia de Moura and Roberto I=
erusalimschy", which is pretty much the definitive treatment of the to=
pic. </div></blockquote><div><br></div><div>I am well aware of this paper. =
They surveyed the messy field and tried try to clean up the existing termin=
ology mess. They were tame in their attempts to clean up the terminology an=
d went with "let's pile up more adjectives path". The conclus=
ion is questionable too. They came to the conclusion that (in their termino=
logy) stackful asymmetric coroutine are the best.</div><div><br></div><div>=
Well they sacrificed performance on two fronts.</div><div><br></div><div>If=
they want stackfullness, they should have chosen fibers. Context switch is=
expensive in the fiber, thus you want to minimize number of switches you d=
o. Going with asymmetric, they doubled the cost, since now when we want to =
do direct transfer between two fibers, we have to first go back to the sche=
duler.</div></div></blockquote><div><br>agree about this; I believe that sy=
mmetric coroutines are better.<br>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div><br></div><div>And, of course, by fav=
oring "stackfulness" they left a lot of performance on the floor.=
</div></div></blockquote><div><br>... but of course disagree about this. As=
I discussed previously, I believe that the stackless coroutines can be imp=
lemented as a compiler optimization on top of stackful coroutines; the loss=
of expressiveness is otherwise too great. <br></div><br>-- gpd<br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_437_1109794321.1444657073640--
------=_Part_436_81250470.1444657073640--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 06:46:40 -0700 (PDT)
Raw View
------=_Part_5570_739744795.1444657600206
Content-Type: multipart/alternative;
boundary="----=_Part_5571_423279235.1444657600216"
------=_Part_5571_423279235.1444657600216
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 6:37:53 AM UTC-7, Giovanni Piero Deretta
wrote:
>
> ... but of course disagree about this. As I discussed previously, I
> believe that the stackless coroutines can be implemented as a compiler
> optimization on top of stackful coroutines;
>
That would be nice. I don't know how to do this efficiently. But if it is
possible I am for it.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5571_423279235.1444657600216
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Monday, October 12, 2015 at 6:37:53 AM UTC-7, Giova=
nni Piero Deretta wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>.=
... but of course disagree about this. As I discussed previously, I believe =
that the stackless coroutines can be implemented as a compiler optimization=
on top of stackful coroutines; </div></blockquote><div><br></div><div>That=
would be nice. I don't know how to do this efficiently. But if it is p=
ossible I am for it.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5571_423279235.1444657600216--
------=_Part_5570_739744795.1444657600206--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 06:56:26 -0700 (PDT)
Raw View
------=_Part_5481_531575836.1444658186669
Content-Type: multipart/alternative;
boundary="----=_Part_5482_1542470303.1444658186669"
------=_Part_5482_1542470303.1444658186669
Content-Type: text/plain; charset=UTF-8
Hi Tongari:
And there are 2 ways to call the coroutine: 1) `operator()` and 2)
> `resume`, where the former is noexcept and the latter can throw.
>
That is a defect. They should have identical signatures and they both
should not be noexcept. Thank you for reporting this. I will fix the
wording.
In the above definition, `initial_suspend` is not surrounded in the
> try-block, does that mean if it throws, when called by `operator()` the
> program will terminate?
>
If the initial suspend throws, we are still trying to create a coroutine
and it is treated similarly if promise constructor throws. Essentially the
caller called a function and it threw into its face.
and when called by `resume`, will it bypass final_suspend? will it reclaim
> the coroutine-frame?
>
For final_suspend, we can can go one of two ways:
1) throwing from final_suspend or any of the await_xxx from its awaitable
is undefined behavior
2) or say that they must be marked noexcept
I will defer for LEWG/Core guidance on this matter.
--
---
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_5482_1542470303.1444658186669
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Tongari:<br><br><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div dir=3D"ltr"><div><div>=C2=A0And there are 2 ways to call the cor=
outine: 1) `operator()` and 2) `resume`, where the former is noexcept and t=
he latter can throw.</div></div></div></blockquote><div><br></div><div>That=
is a defect. They should have identical signatures and they both should no=
t be noexcept. Thank you for reporting this. I will fix the wording.</div><=
div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div><div>In the above definition, `<span style=3D"font-family:arial,sans-=
serif;font-size:small">initial_suspend` is not surrounded in the try-block,=
does that mean if it throws, when called by `</span>operator()<span style=
=3D"font-family:arial,sans-serif;font-size:small">` the program will termin=
ate?</span></div></div></div></blockquote><div><br></div><div>If the initia=
l suspend throws, we are still trying to create a coroutine and it is treat=
ed similarly if promise constructor throws. Essentially the caller called a=
function and it threw into its face.</div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div><span style=3D"font-=
size:small;font-family:arial,sans-serif">and when called by `</span>resume<=
span style=3D"font-size:small;font-family:arial,sans-serif">`, will it bypa=
ss=C2=A0</span><span style=3D"font-family:arial,sans-serif;font-size:small"=
>final_suspend? will it reclaim the coroutine-frame?</span></div></div></di=
v></blockquote><div><br></div><div>For final_suspend, we can can go one of =
two ways:</div><div>1) throwing from final_suspend or any of the await_xxx =
from its awaitable is undefined behavior</div><div>2) or say that they must=
be marked noexcept</div><div><br></div><div>I will defer for LEWG/Core gui=
dance on this matter.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5482_1542470303.1444658186669--
------=_Part_5481_531575836.1444658186669--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 07:07:48 -0700 (PDT)
Raw View
------=_Part_126_1804339393.1444658868477
Content-Type: multipart/alternative;
boundary="----=_Part_127_496074432.1444658868477"
------=_Part_127_496074432.1444658868477
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 2:46:40 PM UTC+1, Gor Nishanov wrote:
>
>
> On Monday, October 12, 2015 at 6:37:53 AM UTC-7, Giovanni Piero Deretta
> wrote:
>>
>> ... but of course disagree about this. As I discussed previously, I
>> believe that the stackless coroutines can be implemented as a compiler
>> optimization on top of stackful coroutines;
>>
>
> That would be nice. I don't know how to do this efficiently. But if it is
> possible I am for it.
>
I'm not a compiler writer, but it seems to me that this requires exactly
the same analysis that is required to remove allocations of the generator
state:
f1 is the caller, f2 is the callee. When f1 instantiates a new coroutine
with f2, it gets a continuation object (or context_handler or or
coroutine_handle or whatever you want to call it). This object represent a
pointer to the halted coroutine state (a single frame for a stackless
generator, a full call stack for a stackful coroutine). Now, you guys have
already implemented an analysis that, if, in f2, no pointer to the state of
the coroutine running f2 ever escapes, you can simply allocate the statein
the stack of f1.
But you can apply the same analysis f2 as well: when it is resumed it gets
(implicitly or explicitly) a continuation to the now suspended f1. If
*between to resumption points in f2*, this continuation does not escape, we
know that f1 will not be resumed outside of f2 control, so we can
temporarily use its stack for every subroutine stack. Only the frame of f2
need to be explicitly allocated, as we know it is the only live frame at
the point the coroutine is suspoended.
--
---
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_127_496074432.1444658868477
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, October 12, 2015 at 2:46:40 PM UTC+1, Gor Nisha=
nov wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br=
>On Monday, October 12, 2015 at 6:37:53 AM UTC-7, Giovanni Piero Deretta wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div>... but of course disagree=
about this. As I discussed previously, I believe that the stackless corout=
ines can be implemented as a compiler optimization on top of stackful corou=
tines; </div></blockquote><div><br></div><div>That would be nice. I don'=
;t know how to do this efficiently. But if it is possible I am for it.</div=
></div></blockquote><div><br>I'm not a compiler writer, but it seems to=
me that this requires exactly the same analysis that is required to remove=
allocations of the generator state:<br><br>f1 is the caller, f2 is the cal=
lee. When f1 instantiates a new coroutine with f2, it gets a continuation o=
bject (or context_handler or=C2=A0 or coroutine_handle or whatever you want=
to call it). This object represent a pointer to the halted coroutine state=
(a single frame for a stackless generator, a full call stack for a stackfu=
l coroutine). Now, you guys have already implemented an analysis that, if, =
in f2, no pointer to the state of the coroutine running f2 ever escapes, yo=
u can simply allocate the statein the stack of f1.<br><br>But you can apply=
the same analysis f2 as well: when it is resumed it gets (implicitly or ex=
plicitly) a continuation to the now suspended f1. If *between to resumption=
points in f2*, this continuation does not escape, we know that f1 will not=
be resumed outside of f2 control, so we can temporarily use its stack for =
every subroutine stack. Only the frame of f2 need to be explicitly allocate=
d, as we know it is the only live frame at the point the coroutine is suspo=
ended. <br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_127_496074432.1444658868477--
------=_Part_126_1804339393.1444658868477--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 07:18:09 -0700 (PDT)
Raw View
------=_Part_5686_1074042531.1444659490079
Content-Type: multipart/alternative;
boundary="----=_Part_5687_1758977399.1444659490079"
------=_Part_5687_1758977399.1444659490079
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 7:07:48 AM UTC-7, Giovanni Piero Deretta
wrote:
> f1 is the caller, f2 is the callee. When f1 instantiates a new coroutine
> with f2, it gets a continuation object (or context_handler or or
> coroutine_handle or whatever you want to call it). This object represent a
> pointer to the halted coroutine state (a single frame for a stackless
> generator, a full call stack for a stackful coroutine). Now, you guys have
> already implemented an analysis that, if, in f2, no pointer to the state of
> the coroutine running f2 ever escapes, you can simply allocate the statein
> the stack of f1.
>
I understand what you are saying, but to me, it is not stackful suspension.
It is an illusion of stackful suspension. It is only possible for cases
where the call sequence has static nesting (including the cases where tail
recursion elimination optimizaiton is applied).
Triple-A suggestion from P0054 (automatically awaited awaitables) will
extend the illusion even further supporting dynamic stack structure
wherever we cannot do the elision, and, combined with specialized allocator
that does some kind of segmented stacks, you may be able to achieve
something close to stackful in appearance.
But, I think that there still be workloads when fibers will be more
efficient than what I described above. Thus I view fibers and coroutines
complementary, neither one can be a complete replacement of each other, as
there will be case when using one will be more appropriate than the other.
--
---
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_5687_1758977399.1444659490079
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, October 12, 2015 at 7:07:48 AM UTC-7, G=
iovanni Piero Deretta wrote:<div>=C2=A0</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div>f1 is the caller, f2 is the callee. Wh=
en f1 instantiates a new coroutine with f2, it gets a continuation object (=
or context_handler or=C2=A0 or coroutine_handle or whatever you want to cal=
l it). This object represent a pointer to the halted coroutine state (a sin=
gle frame for a stackless generator, a full call stack for a stackful corou=
tine). Now, you guys have already implemented an analysis that, if, in f2, =
no pointer to the state of the coroutine running f2 ever escapes, you can s=
imply allocate the statein the stack of f1.<br></div></div></blockquote><di=
v><br></div><div>I understand what you are saying, but to me, it is not sta=
ckful suspension. It is an illusion of stackful suspension. It is only poss=
ible for cases where the call sequence has static nesting (including the ca=
ses where tail recursion elimination optimizaiton is applied).=C2=A0</div><=
div><br></div><div>Triple-A suggestion from P0054 (automatically awaited aw=
aitables) will extend the illusion even further supporting dynamic stack st=
ructure wherever we cannot do the elision, and, combined with specialized a=
llocator that does some kind of segmented stacks, you may be able to achiev=
e something close to stackful in appearance.</div><div><br></div><div>But, =
I think that there still be workloads when fibers will be more efficient th=
an what I described above. Thus I view fibers and coroutines complementary,=
neither one can be a complete replacement of each other, as there will be =
case when using one will be more appropriate than the other.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5687_1758977399.1444659490079--
------=_Part_5686_1074042531.1444659490079--
.
Author: TONGARI J <tongari95@gmail.com>
Date: Mon, 12 Oct 2015 22:20:57 +0800
Raw View
--047d7bea2f98b694fc0521e90997
Content-Type: text/plain; charset=UTF-8
Hi Gor,
2015-10-12 21:56 GMT+08:00 Gor Nishanov <gornishanov@gmail.com>:
> Hi Tongari:
>
> And there are 2 ways to call the coroutine: 1) `operator()` and 2)
>> `resume`, where the former is noexcept and the latter can throw.
>>
>
> That is a defect. They should have identical signatures and they both
> should not be noexcept. Thank you for reporting this. I will fix the
> wording.
>
Actually P0057R0 declares both of them without noexcept, I was refering
to <experimental/resumable> shipped with MSVC where operator() is noexcept
and resume is not, which makes sense to me. I think operator() should be
noexcept so it was a doc mistake in P0057R0, but now you're saying they
both should not be noexcept? then why 2 names for the same thing?
> In the above definition, `initial_suspend` is not surrounded in the
>> try-block, does that mean if it throws, when called by `operator()` the
>> program will terminate?
>>
>
> If the initial suspend throws, we are still trying to create a coroutine
> and it is treated similarly if promise constructor throws. Essentially the
> caller called a function and it threw into its face.
>
> and when called by `resume`, will it bypass final_suspend? will it
>> reclaim the coroutine-frame?
>>
>
The above questions are not resolved. Any hint?
> For final_suspend, we can can go one of two ways:
> 1) throwing from final_suspend or any of the await_xxx from its awaitable
> is undefined behavior
> 2) or say that they must be marked noexcept
>
> I will defer for LEWG/Core guidance on this matter.
>
1) Why not a defined behavior that calls std::terminate?
--
---
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/.
--047d7bea2f98b694fc0521e90997
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi Gor,<br><div class=3D"gmail_extra"><br><div class=3D"gm=
ail_quote">2015-10-12 21:56 GMT+08:00 Gor Nishanov <span dir=3D"ltr"><<a=
href=3D"mailto:gornishanov@gmail.com" target=3D"_blank">gornishanov@gmail.=
com</a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0p=
x 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bo=
rder-left-style:solid;padding-left:1ex"><div dir=3D"ltr">Hi Tongari:<span c=
lass=3D""><br><br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-=
left-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div>=C2=A0And the=
re are 2 ways to call the coroutine: 1) `operator()` and 2) `resume`, where=
the former is noexcept and the latter can throw.</div></div></div></blockq=
uote><div><br></div></span><div>That is a defect. They should have identica=
l signatures and they both should not be noexcept. Thank you for reporting =
this. I will fix the wording.</div></div></blockquote><div><br></div><div>A=
ctually P0057R0 declares both of them without noexcept, I was refering to=
=C2=A0<experimental/resumable> shipped with MSVC where operator() is =
noexcept and resume is not, which makes sense to me. I think operator() sho=
uld be noexcept so it was a doc mistake in P0057R0, but now you're sayi=
ng they both=C2=A0should not be noexcept? then why 2 names for the same thi=
ng?</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);b=
order-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">=
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p=
x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef=
t-style:solid;padding-left:1ex"><div dir=3D"ltr"><div><div>In the above def=
inition, `<span style=3D"font-family:arial,sans-serif;font-size:small">init=
ial_suspend` is not surrounded in the try-block, does that mean if it throw=
s, when called by `</span>operator()<span style=3D"font-family:arial,sans-s=
erif;font-size:small">` the program will terminate?</span></div></div></div=
></blockquote><div><br></div></span><div>If the initial suspend throws, we =
are still trying to create a coroutine and it is treated similarly if promi=
se constructor throws. Essentially the caller called a function and it thre=
w into its face.</div><span class=3D""><div><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border=
-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div=
dir=3D"ltr"><div><div><span style=3D"font-size:small;font-family:arial,san=
s-serif">and when called by `</span>resume<span style=3D"font-size:small;fo=
nt-family:arial,sans-serif">`, will it bypass=C2=A0</span><span style=3D"fo=
nt-family:arial,sans-serif;font-size:small">final_suspend? will it reclaim =
the coroutine-frame?</span></div></div></div></blockquote></span></div></bl=
ockquote><div><br></div><div>The above questions are not resolved. Any hint=
?</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);b=
order-left-style:solid;padding-left:1ex"><div dir=3D"ltr"><span class=3D"">=
<div></div></span><div>For final_suspend, we can can go one of two ways:</d=
iv><div>1) throwing from final_suspend or any of the await_xxx from its awa=
itable is undefined behavior</div><div>2) or say that they must be marked n=
oexcept</div><div><br></div><div>I will defer for LEWG/Core guidance on thi=
s matter.</div></div></blockquote><div><br></div><div>1) Why not a defined =
behavior that calls std::terminate?</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bea2f98b694fc0521e90997--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 07:45:32 -0700 (PDT)
Raw View
------=_Part_4634_548236635.1444661133115
Content-Type: multipart/alternative;
boundary="----=_Part_4635_990363361.1444661133116"
------=_Part_4635_990363361.1444661133116
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 3:18:10 PM UTC+1, Gor Nishanov wrote:
>
>
>
> On Monday, October 12, 2015 at 7:07:48 AM UTC-7, Giovanni Piero Deretta
> wrote:
>
>
>> f1 is the caller, f2 is the callee. When f1 instantiates a new coroutine
>> with f2, it gets a continuation object (or context_handler or or
>> coroutine_handle or whatever you want to call it). This object represent a
>> pointer to the halted coroutine state (a single frame for a stackless
>> generator, a full call stack for a stackful coroutine). Now, you guys have
>> already implemented an analysis that, if, in f2, no pointer to the state of
>> the coroutine running f2 ever escapes, you can simply allocate the statein
>> the stack of f1.
>>
>
> I understand what you are saying, but to me, it is not stackful
> suspension. It is an illusion of stackful suspension. It is only possible
> for cases where the call sequence has static nesting (including the cases
> where tail recursion elimination optimizaiton is applied).
>
The objective is being no worse than a purely stackless generator
implementation, which doesn't have stackful suspension by definition, for
all use cases in which a generator is sufficient, while still allowing
stackful suspension if desired. Do you have an example where a stackless
coroutine is sufficient but the above analysis won't be able to infer the
"stackless-ness"?
-- gpd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4635_990363361.1444661133116
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 3:18:10 PM UTC+1, Gor Nishanov wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br><br>On Monday, O=
ctober 12, 2015 at 7:07:48 AM UTC-7, Giovanni Piero Deretta wrote:<div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>f1 i=
s the caller, f2 is the callee. When f1 instantiates a new coroutine with f=
2, it gets a continuation object (or context_handler or=C2=A0 or coroutine_=
handle or whatever you want to call it). This object represent a pointer to=
the halted coroutine state (a single frame for a stackless generator, a fu=
ll call stack for a stackful coroutine). Now, you guys have already impleme=
nted an analysis that, if, in f2, no pointer to the state of the coroutine =
running f2 ever escapes, you can simply allocate the statein the stack of f=
1.<br></div></div></blockquote><div><br></div><div>I understand what you ar=
e saying, but to me, it is not stackful suspension. It is an illusion of st=
ackful suspension. It is only possible for cases where the call sequence ha=
s static nesting (including the cases where tail recursion elimination opti=
mizaiton is applied).=C2=A0</div></div></blockquote><div><br>The objective =
is being no worse than a purely stackless generator implementation, which d=
oesn't have stackful suspension by definition, for all use cases in whi=
ch a generator is sufficient, while still allowing stackful suspension if d=
esired. Do you have an example where a stackless coroutine is sufficient bu=
t the above analysis won't be able to infer the "stackless-ness&qu=
ot;? <br></div><br>-- gpd<br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4635_990363361.1444661133116--
------=_Part_4634_548236635.1444661133115--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 12 Oct 2015 09:54:39 -0700 (PDT)
Raw View
------=_Part_639_1507165652.1444668879295
Content-Type: multipart/alternative;
boundary="----=_Part_640_1822501188.1444668879295"
------=_Part_640_1822501188.1444668879295
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 9:17:05 AM UTC-4, Gor Nishanov wrote:
>
>
> On Monday, October 12, 2015 at 5:52:07 AM UTC-7, Giovanni Piero Deretta=
=20
> wrote:
>>
>> The terms stackful and stackless come from "Revisiting Coroutines" by An=
a=20
>> L =CC=81cia de Moura and Roberto Ierusalimschy", which is pretty much th=
e=20
>> definitive treatment of the topic.=20
>>
>
> I am well aware of this paper. They surveyed the messy field and tried tr=
y=20
> to clean up the existing terminology mess. They were tame in their attemp=
ts=20
> to clean up the terminology and went with "let's pile up more adjectives=
=20
> path".
> ...
> We control the language we use in C++. Whatever terms we chose can=20
> influence the rest of the industry.
>
Which is why we shouldn't take words that the industry already has firm=20
definitions for and make them mean something totally different. That only=
=20
creates needless confusion.
If a bunch of sources, from lots of different people who are experts at the=
=20
field, define a word one way, then it is wrong for us to arbitrarily define=
=20
it another way. If most people agree that "coroutine" means "function who's=
=20
execution can be halted and resumed at the point where it was halted,=20
regardless of where in the call stack the halting/resuming happened", then=
=20
it is wrong for us to define C++ coroutines to be "resumable functions."
I understand the desire to what to call your feature "coroutines". But when=
=20
the functionality is explained to most people who know them from other=20
languages, they simply will not agree with your definition.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_640_1822501188.1444668879295
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 9:17:05 AM UTC-4, Gor Nishanov wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><br>On Monday, Octob=
er 12, 2015 at 5:52:07 AM UTC-7, Giovanni Piero Deretta wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div>The terms stackful and stackless come from =
"Revisiting Coroutines" by Ana L =CC=81cia de Moura and Roberto I=
erusalimschy", which is pretty much the definitive treatment of the to=
pic. </div></blockquote><div><br></div><div>I am well aware of this paper. =
They surveyed the messy field and tried try to clean up the existing termin=
ology mess. They were tame in their attempts to clean up the terminology an=
d went with "let's pile up more adjectives path".<br></div><d=
iv>...<br></div><div>We control the language we use in C++. Whatever terms =
we chose can influence the rest of the industry.</div></div></blockquote><d=
iv><br>Which is why we shouldn't take words that the industry already h=
as firm definitions for and make them mean something totally different. Tha=
t only creates needless confusion.<br><br>If a bunch of sources, from lots =
of different people who are experts at the field, define a word one way, th=
en it is wrong for us to arbitrarily define it another way. If most people =
agree that "coroutine" means "function who's execution c=
an be halted and resumed at the point where it was halted, regardless of wh=
ere in the call stack the halting/resuming happened", then it is wrong=
for us to define C++ coroutines to be "resumable functions."<br>=
<br>I understand the desire to what to call your feature "coroutines&q=
uot;. But when the functionality is explained to most people who know them =
from other languages, they simply will not agree with your definition.<br><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_640_1822501188.1444668879295--
------=_Part_639_1507165652.1444668879295--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 10:21:55 -0700 (PDT)
Raw View
------=_Part_1163_146041053.1444670515408
Content-Type: multipart/alternative;
boundary="----=_Part_1164_1560084094.1444670515408"
------=_Part_1164_1560084094.1444670515408
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 9:54:39 AM UTC-7, Nicol Bolas wrote:
>
> I understand the desire to what to call your feature "coroutines".
>
Do not attempt to read my mind. The proposals I brought to Lenexa
https://isocpp.org/files/papers/N4402.pdf - overview
https://isocpp.org/files/papers/N4403.pdf - wording
I specifically used resumable functions, as not to use coroutine so as not
to confuse people.
That was the change from post-Urbana mailining. I requested a vote to
approve the rename and there was no consensus.
So the rename was not approved and they stayed coroutines.
After the Lenexa vote, I decided to embrace the word coroutines. And since
my preference is for short descriptive words, from now one, when I say
coroutine, thread and fiber, I mean:
first class object language supported stackless asymmetric coroutine or
generalized function => coroutine
first class object stackful symmetric coroutine or user-mode cooperative
scheduled thread => fiber
first class object heavy-weight thread equivalent to OS thread => thread
Of course, I did not mind that terminology before Lenexa vote, but, I was
not insisting on it, since resumable function is short and descriptive
enough.
--
---
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_1164_1560084094.1444670515408
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, October 12, 2015 at 9:54:39 AM UTC-7, Nicol Bol=
as wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>I understand the=
desire to what to call your feature "coroutines".=C2=A0<br></div=
></blockquote><div><br></div><div>Do not attempt to read my mind. The propo=
sals I brought to Lenexa</div><div><br></div><div>https://isocpp.org/files/=
papers/N4402.pdf - overview<br></div><div>https://isocpp.org/files/papers/N=
4403.pdf - wording<br></div><div><br></div><div>I specifically used resumab=
le functions, as not to use coroutine so as not to confuse people.=C2=A0</d=
iv><div>That was the change from post-Urbana mailining. I requested a vote =
to approve the rename and there was no consensus.</div><div>So the rename w=
as not approved and they stayed coroutines.</div><div><br>After the Lenexa =
vote, I decided to embrace the word coroutines. And since my preference is =
for short descriptive words, from now one, when I say coroutine, thread and=
fiber, I mean:</div><div><br></div><div>first class object language suppor=
ted stackless asymmetric coroutine or generalized function =3D> coroutin=
e</div><div>first class object stackful symmetric coroutine or user-mode co=
operative scheduled thread =3D> fiber</div><div>first class object heavy=
-weight thread equivalent to OS thread =3D> thread</div><div><br></div><=
div>Of course, I did not mind that terminology before Lenexa vote, but, I w=
as not insisting on it, since resumable function is short and descriptive e=
nough.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1164_1560084094.1444670515408--
------=_Part_1163_146041053.1444670515408--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 11:15:31 -0700 (PDT)
Raw View
------=_Part_10_2094817780.1444673731337
Content-Type: multipart/alternative;
boundary="----=_Part_11_1285978790.1444673731338"
------=_Part_11_1285978790.1444673731338
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 7:45:33 AM UTC-7, Giovanni Piero Deretta
wrote:
>
> Do you have an example where a stackless coroutine is sufficient but the
> above analysis won't be able to infer the "stackless-ness"?
>
I have an example of the opposite. It is an example when putting the
following function on a fiber, as opposed to making it into a coroutine
with all optimizations enabled (tail recursion, heap elision, custom
allocator), the fiber should beat the coroutine for at least some values of
to and from.
void f(int from, int to) {
auto diff = to - from;
if (diff == 0)
return;
if (diff == 1) {
yield(from);
return;
}
auto mid = (from + to) / 2;
f(from, mid);
f(mid, to);
}
Since the tail recursion will eliminate only one of the recursive calls, we
will be comparing two bucket of operations.
1 fiber creation/destruction versus N coroutine creations/destructions.
N coroutine suspensions vs N fiber suspensions.
N function calls/returns N coroutine calls/returns. ~ equivalent
Fiber creation is more expensive than coroutine creation, but we are doing
just one of them, versus N for coroutines.
Coroutine suspension/resumption is cheaper than fiber suspension/resumption.
So, depending on N and cost of the context switch, fibers may be still
faster than super optimized attempt to build a fiber out of stackless
coroutines.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_11_1285978790.1444673731338
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, October 12, 2015 at 7:45:33 AM UTC-7, Giovanni =
Piero Deretta wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>=C2=
=A0Do you have an example where a stackless coroutine is sufficient but the=
above analysis won't be able to infer the "stackless-ness"? =
<br></div></blockquote><div><br></div><div>I have an example of the opposit=
e. It is an example when putting the following function on a fiber, as oppo=
sed to making it into a coroutine with all optimizations enabled (tail recu=
rsion, heap elision, custom allocator), the fiber should beat the coroutine=
for at least some values of to and from.</div><div><br></div><div class=3D=
"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: bre=
ak-word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"=
><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled=
-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">from</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> to</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> diff </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> to </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">-</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">from</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">if</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">di=
ff </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">diff </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>yield</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">from</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ret=
urn</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br>=C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">aut=
o</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> mid =C2=
=A0</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">from</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> to</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">/</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #066;" class=3D"styled-by-prettify">2</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br><br>=C2=A0 =C2=A0 f</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">from</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> mid</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>=C2=A0 =C2=A0 f</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">mid</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> to</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br><br></span></div></code></div><d=
iv><br>Since the tail recursion will eliminate only one of the recursive ca=
lls, we will be comparing two bucket of operations.</div><div>1 fiber creat=
ion/destruction versus N coroutine creations/destructions.</div><div>N coro=
utine suspensions vs N fiber suspensions.</div><div>N function calls/return=
s N coroutine calls/returns. ~ equivalent</div><div><br></div><div>Fiber cr=
eation is more expensive than coroutine creation, but we are doing just one=
of them, versus N for coroutines.</div><div>Coroutine suspension/resumptio=
n is cheaper than fiber suspension/resumption.</div><div><br></div><div>So,=
depending on N and cost of the context switch, fibers may be still faster =
than super optimized attempt to build a fiber out of stackless coroutines.=
=C2=A0</div><div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_11_1285978790.1444673731338--
------=_Part_10_2094817780.1444673731337--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 21:40:24 +0100
Raw View
On Mon, Oct 12, 2015 at 7:15 PM, Gor Nishanov <gornishanov@gmail.com> wrote:
> On Monday, October 12, 2015 at 7:45:33 AM UTC-7, Giovanni Piero Deretta
> wrote:
>>
>> Do you have an example where a stackless coroutine is sufficient but the
>> above analysis won't be able to infer the "stackless-ness"?
>
>
> I have an example of the opposite. It is an example when putting the
> following function on a fiber, as opposed to making it into a coroutine with
> all optimizations enabled (tail recursion, heap elision, custom allocator),
> the fiber should beat the coroutine for at least some values of to and from.
>
> void f(int from, int to) {
> auto diff = to - from;
> if (diff == 0)
> return;
>
> if (diff == 1) {
> yield(from);
> return;
> }
>
> auto mid = (from + to) / 2;
>
> f(from, mid);
> f(mid, to);
> }
>
well, I wanted an example expressible with a stackless coroutine that
is not inferrable by the compiler, i.e. an example where the compiler
wouldn't be able to prove that allocating a single frame is sufficient
while the programmer can . This is not it.
>
> Since the tail recursion will eliminate only one of the recursive calls, we
> will be comparing two bucket of operations.
> 1 fiber creation/destruction versus N coroutine creations/destructions.
> N coroutine suspensions vs N fiber suspensions.
> N function calls/returns N coroutine calls/returns. ~ equivalent
>
> Fiber creation is more expensive than coroutine creation, but we are doing
> just one of them, versus N for coroutines.
> Coroutine suspension/resumption is cheaper than fiber suspension/resumption.
>
I do not see why that would be the case, the same optimisations
available for stackless coroutines are applicable to stackful
coroutines. Sure a pure library stackful coroutine implementation
might (or not) be slower than an optimized compiler assisted stackless
generator, but in principle there are no differences, other than
allocating a single stack vs N separate frames.
Also note that if the compiler doesn't have a bound on the recursion
depth, it might have an hard time stack allocating the N separate
frames.
> So, depending on N and cost of the context switch, fibers may be still
> faster than super optimized attempt to build a fiber out of stackless
> coroutines.
>
exactly.
-- gpd
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.