Topic: P0099 suggestion: Minimal support for asymmetric suspend/resume
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 21:53:03 -0700 (PDT)
Raw View
------=_Part_4114_44081114.1444625583767
Content-Type: multipart/alternative;
boundary="----=_Part_4115_1156246192.1444625583767"
------=_Part_4115_1156246192.1444625583767
Content-Type: text/plain; charset=UTF-8
With P0057 and P0099, we have two choices for our coroutine needs:
asymmetric, stackless and symmetric, stackful.
Having a stack and not having a stack are more or less orthogonal relative
to the symmetry of coroutine execution. Well, not really; it'd be very
difficult to have stackless symmetric coroutines. But both symmetric and
asymmetric are legitimate designs for stackful coroutines.
I agree that it is important to support symmetric stackful coroutines, due
to the context switching overhead. You'll get no arguments here.
The problem is that it's *really* hard to support asymmetric coroutines
given the current design. There is not only no linkage between the calling
context and the callee, there is no way to create such linkage.
Oh sure, you can have a lambda function that captures the calling context.
The problem is that the lambda would then have to pass that up the entire
call stack to whomever it is that actually suspends.
Not everyone suspends in the base function, after all.
Again, I agree that it should not be the default case. But give us at least
*something* to allow for the asymmetric case.
Possible suggestions:
1) Give `execution_context` a function to suspend the current context,
resuming the previous one. The previous context being the context that was
current when it called our `operator()` function.
This naturally requires that `execution_context` store a reference to a
previous context. If the previous context was ended in the meantime, it's
no different from any case where you attempt to resume a dead handle.
2) If having a named function for this is considered bad form, simply give
`execution_context` a function that returns the previous context. That way,
it can use `operator()` the normal way. Again, this requires that
`execution_context` store a reference to the previous context.
3) If having `execution_context` store the previous context is just too
much... well, give us a pointer. Have `execution_context` be able to be
transformed into a pointer (much like P0057's coroutine_handle can be).
Every `execution_context` which refers to the same state has the same
pointer, which will be different for every distinct context state that
exists. Obviously, `execution_context`s which have finished (operator bool
returns false) return nullptr.
The idea here is that the user can associate the pointer for an
`execution_context` with the execution_context that will call it. Yes, this
would have to be done via a global table, which is generally a bad idea.
But at least it would *work*. If we can't have `execution_context` track
the caller for us, it would at least allow us to track it ourselves.
--
---
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_4115_1156246192.1444625583767
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">With P0057 and P0099, we have two choices for our coroutin=
e needs: asymmetric, stackless and symmetric, stackful.<br><br>Having a sta=
ck and not having a stack are more or less orthogonal relative to the symme=
try of coroutine execution. Well, not really; it'd be very difficult to=
have stackless symmetric coroutines. But both symmetric and asymmetric are=
legitimate designs for stackful coroutines.<br><br>I agree that it is impo=
rtant to support symmetric stackful coroutines, due to the context switchin=
g overhead. You'll get no arguments here.<br><br>The problem is that it=
's <i>really</i> hard to support asymmetric coroutines given the curren=
t design. There is not only no linkage between the calling context and the =
callee, there is no way to create such linkage.<br><br>Oh sure, you can hav=
e a lambda function that captures the calling context. The problem is that =
the lambda would then have to pass that up the entire call stack to whomeve=
r it is that actually suspends.<br><br>Not everyone suspends in the base fu=
nction, after all.<br><br>Again, I agree that it should not be the default =
case. But give us at least <i>something</i> to allow for the asymmetric cas=
e.<br><br>Possible suggestions:<br><br>1) Give `execution_context` a functi=
on to suspend the current context, resuming the previous one. The previous =
context being the context that was current when it called our `operator()` =
function.<br><br>This
naturally requires that `execution_context` store a reference to a=20
previous context. If the previous context was ended in the meantime,=20
it's no different from any case where you attempt to resume a dead=20
handle.<br><br>2) If having a named function for this is considered bad for=
m, simply give `execution_context` a function that returns the previous con=
text. That way, it can use `operator()` the normal way. Again, this require=
s that `execution_context` store a reference to the previous context.<br><b=
r>3) If having `execution_context` store the previous context is just too m=
uch... well, give us a pointer. Have `execution_context` be able to be tran=
sformed into a pointer (much like P0057's coroutine_handle can be). Eve=
ry `execution_context` which refers to the same state has the same pointer,=
which will be different for every distinct context state that exists. Obvi=
ously, `execution_context`s which have finished (operator bool returns fals=
e) return nullptr.<br><br>The idea here is that the user can associate the =
pointer for an `execution_context` with the execution_context that will cal=
l it. Yes, this would have to be done via a global table, which is generall=
y a bad idea.<br><br>But at least it would <i>work</i>. If we can't hav=
e `execution_context` track the caller for us, it would at least allow us t=
o track it ourselves.<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_4115_1156246192.1444625583767--
------=_Part_4114_44081114.1444625583767--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 11 Oct 2015 21:57:35 -0700 (PDT)
Raw View
------=_Part_4188_1425637774.1444625855931
Content-Type: multipart/alternative;
boundary="----=_Part_4189_1210257535.1444625855931"
------=_Part_4189_1210257535.1444625855931
Content-Type: text/plain; charset=UTF-8
On Monday, October 12, 2015 at 12:53:04 AM UTC-4, Nicol Bolas wrote:
>
> With P0057 and P0099, we have two choices for our coroutine needs:
> asymmetric, stackless and symmetric, stackful.
>
> Having a stack and not having a stack are more or less orthogonal relative
> to the symmetry of coroutine execution. Well, not really; it'd be very
> difficult to have stackless symmetric coroutines. But both symmetric and
> asymmetric are legitimate designs for stackful coroutines.
>
> I agree that it is important to support symmetric stackful coroutines, due
> to the context switching overhead. You'll get no arguments here.
>
> The problem is that it's *really* hard to support asymmetric coroutines
> given the current design. There is not only no linkage between the calling
> context and the callee, there is no way to create such linkage.
>
> Oh sure, you can have a lambda function that captures the calling context.
> The problem is that the lambda would then have to pass that up the entire
> call stack to whomever it is that actually suspends.
>
> Not everyone suspends in the base function, after all.
>
> Again, I agree that it should not be the default case. But give us at
> least *something* to allow for the asymmetric case.
>
> Possible suggestions:
>
> 1) Give `execution_context` a function to suspend the current context,
> resuming the previous one. The previous context being the context that was
> current when it called our `operator()` function.
>
> This naturally requires that `execution_context` store a reference to a
> previous context. If the previous context was ended in the meantime, it's
> no different from any case where you attempt to resume a dead handle.
>
> 2) If having a named function for this is considered bad form, simply give
> `execution_context` a function that returns the previous context. That way,
> it can use `operator()` the normal way. Again, this requires that
> `execution_context` store a reference to the previous context.
>
> 3) If having `execution_context` store the previous context is just too
> much... well, give us a pointer. Have `execution_context` be able to be
> transformed into a pointer (much like P0057's coroutine_handle can be).
> Every `execution_context` which refers to the same state has the same
> pointer, which will be different for every distinct context state that
> exists. Obviously, `execution_context`s which have finished (operator bool
> returns false) return nullptr.
>
> The idea here is that the user can associate the pointer for an
> `execution_context` with the execution_context that will call it. Yes, this
> would have to be done via a global table, which is generally a bad idea.
>
> But at least it would *work*. If we can't have `execution_context` track
> the caller for us, it would at least allow us to track it ourselves.
>
Oh, and a word on option #3: P0057 allows `coroutine_handle`s to be
transformed to/from pointers, so that they can be used as callback data
values in C-style APIs. That may be important in some specialized cases
when wanting to yield across C-style APIs. So there are good reasons for
having it besides supporting asymmetric coroutines.
While I'd prefer option #2, #3 will at least be functional.
--
---
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_4189_1210257535.1444625855931
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 12:53:04 AM UTC-4, Nicol Bolas 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">With P0057 and P0099=
, we have two choices for our coroutine needs: asymmetric, stackless and sy=
mmetric, stackful.<br><br>Having a stack and not having a stack are more or=
less orthogonal relative to the symmetry of coroutine execution. Well, not=
really; it'd be very difficult to have stackless symmetric coroutines.=
But both symmetric and asymmetric are legitimate designs for stackful coro=
utines.<br><br>I agree that it is important to support symmetric stackful c=
oroutines, due to the context switching overhead. You'll get no argumen=
ts here.<br><br>The problem is that it's <i>really</i> hard to support =
asymmetric coroutines given the current design. There is not only no linkag=
e between the calling context and the callee, there is no way to create suc=
h linkage.<br><br>Oh sure, you can have a lambda function that captures the=
calling context. The problem is that the lambda would then have to pass th=
at up the entire call stack to whomever it is that actually suspends.<br><b=
r>Not everyone suspends in the base function, after all.<br><br>Again, I ag=
ree that it should not be the default case. But give us at least <i>somethi=
ng</i> to allow for the asymmetric case.<br><br>Possible suggestions:<br><b=
r>1) Give `execution_context` a function to suspend the current context, re=
suming the previous one. The previous context being the context that was cu=
rrent when it called our `operator()` function.<br><br>This
naturally requires that `execution_context` store a reference to a=20
previous context. If the previous context was ended in the meantime,=20
it's no different from any case where you attempt to resume a dead=20
handle.<br><br>2) If having a named function for this is considered bad for=
m, simply give `execution_context` a function that returns the previous con=
text. That way, it can use `operator()` the normal way. Again, this require=
s that `execution_context` store a reference to the previous context.<br><b=
r>3) If having `execution_context` store the previous context is just too m=
uch... well, give us a pointer. Have `execution_context` be able to be tran=
sformed into a pointer (much like P0057's coroutine_handle can be). Eve=
ry `execution_context` which refers to the same state has the same pointer,=
which will be different for every distinct context state that exists. Obvi=
ously, `execution_context`s which have finished (operator bool returns fals=
e) return nullptr.<br><br>The idea here is that the user can associate the =
pointer for an `execution_context` with the execution_context that will cal=
l it. Yes, this would have to be done via a global table, which is generall=
y a bad idea.<br><br>But at least it would <i>work</i>. If we can't hav=
e `execution_context` track the caller for us, it would at least allow us t=
o track it ourselves.<br></div></blockquote><div><br>Oh, and a word on opti=
on #3: P0057 allows `coroutine_handle`s to be transformed to/from pointers,=
so that they can be used as callback data values in C-style APIs. That may=
be important in some specialized cases when wanting to yield across C-styl=
e APIs. So there are good reasons for having it besides supporting asymmetr=
ic coroutines.<br><br>While I'd prefer option #2, #3 will at least be f=
unctional.<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_4189_1210257535.1444625855931--
------=_Part_4188_1425637774.1444625855931--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Sun, 11 Oct 2015 22:18:34 -0700 (PDT)
Raw View
------=_Part_282_1221219854.1444627114449
Content-Type: multipart/alternative;
boundary="----=_Part_283_1364048933.1444627114449"
------=_Part_283_1364048933.1444627114449
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hmm... I think you can take execution_context as proposed in p0099 and=20
build a higher level abstraction on top without losing any efficiency.=20
Something like this:
fiber ctors + swap + assignment + destructor +
fiber.join() =E2=80=93 resumes the fiber (remembers the context who called =
it)
this_fiber::suspend() =E2=80=93 yields back to whomever called it
this_fiber::switch_to(another fiber) =E2=80=93 direct switch to another fib=
er. the=20
caller context is transferred to the new fiber.
I think at the moment. execution_context is as minimal and as efficient as=
=20
it can be.
--=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_283_1364048933.1444627114449
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hmm... I think you can take execution_context as proposed =
in p0099 and build a higher level abstraction on top without losing any eff=
iciency.=C2=A0<div>Something like this:</div><div><br></div><div><p class=
=3D"MsoNormal">fiber ctors + swap + assignment + destructor +<o:p></o:p></p=
>
<p class=3D"MsoNormal">fiber.join() =E2=80=93 resumes the fiber (remembers =
the context who
called it)<o:p></o:p></p>
<p class=3D"MsoNormal">this_fiber::suspend() =E2=80=93 yields back to whome=
ver called it<o:p></o:p></p>
<p class=3D"MsoNormal">this_fiber::switch_to(another fiber) =E2=80=93 direc=
t switch to
another fiber. the caller context is transferred to the new fiber.<o:p></o:=
p></p><p class=3D"MsoNormal"><br></p><p class=3D"MsoNormal">I think at the =
moment. execution_context is as minimal and as efficient as it can be.</p><=
/div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_283_1364048933.1444627114449--
------=_Part_282_1221219854.1444627114449--
.
Author: Oliver Kowalke <oliver.kowalke@gmail.com>
Date: Mon, 12 Oct 2015 10:14:03 +0200
Raw View
--001a1140978cbc411f0521e3ea51
Content-Type: text/plain; charset=UTF-8
2015-10-12 6:53 GMT+02:00 Nicol Bolas <jmckesson@gmail.com>:
> The problem is that it's *really* hard to support asymmetric coroutines
> given the current design. There is not only no linkage between the calling
> context and the callee, there is no way to create such linkage.
>
it is possible as you can see in boost.coroutine2. the library uses
execution_context (blue print for std::Execution_context proposed in
P0099R0 and its predecessors) from boost.context and provides an asymmetric
coroutine API
execution_context is designed to provide symmetric context switching by
intention. it is more efficient in the case of fibers (fibers are unaware
of there predecessors and successors; a internal, customizable scheduler
selects and resumes the next fiber when the current fiber suspends).
asymmetric coroutines, as already described, can easily build upon
execution-context's symmetric context switching.
--
---
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/.
--001a1140978cbc411f0521e3ea51
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:53 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">The problem is that it=
9;s <i>really</i> hard to support asymmetric coroutines given the current d=
esign. There is not only no linkage between the calling context and the cal=
lee, there is no way to create such linkage.<br></div></blockquote><div><br=
></div><div>it is possible as you can see in boost.coroutine2. the library =
uses execution_context (blue print for std::Execution_context proposed in P=
0099R0 and its predecessors) from boost.context and provides an asymmetric =
coroutine API<br></div><div>execution_context is designed to provide symmet=
ric context switching by intention. it is more efficient in the case of fib=
ers (fibers are unaware of there predecessors and successors; a internal, c=
ustomizable scheduler<br></div><div>selects and resumes the next fiber when=
the current fiber suspends).<br></div><div>asymmetric coroutines, as alrea=
dy described, can easily build upon execution-context's symmetric conte=
xt switching.<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 />
--001a1140978cbc411f0521e3ea51--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 12 Oct 2015 09:32:39 -0700 (PDT)
Raw View
------=_Part_617_873234289.1444667559848
Content-Type: multipart/alternative;
boundary="----=_Part_618_1426928661.1444667559849"
------=_Part_618_1426928661.1444667559849
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 1:18:34 AM UTC-4, Gor Nishanov wrote:
>
> Hmm... I think you can take execution_context as proposed in p0099 and=20
> build a higher level abstraction on top without losing any efficiency.
>
None of the options I've suggested involves any loss of efficiency (even=20
options 1 and 2 are just an extra pointer). The default case is still=20
symmetric operation; the possibilities I've outlined simply allow for the=
=20
*chance* to make them asymmetric.
=20
> Something like this:
>
> fiber ctors + swap + assignment + destructor +
>
> fiber.join() =E2=80=93 resumes the fiber (remembers the context who calle=
d it)
>
> this_fiber::suspend() =E2=80=93 yields back to whomever called it
>
The first two are easy enough to do. It's the third part that seems=20
impossible. `execution_context::current` gives you the current=20
`execution_context`, but how do you convert that into a user-defined type?=
=20
That is, how do you implement `this_fiber`, given only=20
`execution_context::current` to work with?
You can't just do some kind of static_cast from an `execution_context` to a=
=20
derived type, since your derived class has actual state (namely, the fiber=
=20
that called it). You need a mapping table from a fiber-created=20
`execution_context`s to actual `fiber` that created it. And that requires=
=20
some way to uniquely associate an `execution_context` with a `fiber`.
That's what option #3 does: provide an identifier for an=20
`execution_context`, so that you can associate objects with it.
I don't know of a way to do that without explicit support from=20
`execution_context`. After all, getting the address of a handle type means=
=20
nothing relative to the object being referenced by the handle.
Also, Boost.Coroutine2 isn't an answer. Despite its claims to the contrary,=
=20
it implement symmetric coroutines. Just look at all of the examples in the=
=20
documentation=20
<http://www.boost.org/doc/libs/1_59_0/libs/coroutine2/doc/html/coroutine2/c=
oroutine/asymmetric.html>:=20
they're not asymmetric at all. All of them are resuming a *specific*=20
coroutine. Not one of them yields execution directly to its caller without=
=20
being explicitly told which coroutine it should yield to. They're=20
generating values for a specific execution context, or retrieving values=20
*from* a specific execution context. Boost.Coroutine2 is all about getting=
=20
values from Boost.Context's symmetric coroutines.
The point of an asymmetric coroutine is that you *don't know* who your=20
caller is. And you don't care. You could be executed from one context one=
=20
time, then resumed from another context later. You don't care which it is;=
=20
you just want to yield back to whomever it was that started you.
Boost.Coroutine2 does not provide this. Well, not without passing a=20
specific object up the callstack to whomever yields (and quite frankly, I=
=20
can do that with `execution_context`).
Remember: we want stackful coroutines precisely because we want to be able=
=20
to yield anywhere. So we may be very far from that lambda, and we=20
absolutely do not want to have to pass the context to yield to through=20
every single function along the way.
--=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_618_1426928661.1444667559849
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, October 12, 2015 at 1:18:34 AM 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">Hmm=
.... I think you can take execution_context as proposed in p0099 and build a=
higher level abstraction on top without losing any efficiency.</div></bloc=
kquote><div><br>None of the options I've suggested involves any loss of=
efficiency (even options 1 and 2 are just an extra pointer). The default c=
ase is still symmetric operation; the possibilities I've outlined simpl=
y allow for the <i>chance</i> to make them asymmetric.<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>Something lik=
e this:</div><div><br></div><div><p class=3D"MsoNormal">fiber ctors + swap =
+ assignment + destructor +</p>
<p class=3D"MsoNormal">fiber.join() =E2=80=93 resumes the fiber (remembers =
the context who
called it)</p>
<p class=3D"MsoNormal">this_fiber::suspend() =E2=80=93 yields back to whome=
ver called it</p></div></div></blockquote><div><br>The first two are easy e=
nough to do. It's the third part that seems impossible. `execution_cont=
ext::current` gives you the current `execution_context`, but how do you con=
vert that into a user-defined type? That is, how do you implement `this_fib=
er`, given only `execution_context::current` to work with?<br><br>You can&#=
39;t just do some kind of static_cast from an `execution_context` to a deri=
ved type, since your derived class has actual state (namely, the fiber that=
called it). You need a mapping table from a fiber-created `execution_conte=
xt`s to actual `fiber` that created it. And that requires some way to uniqu=
ely associate an `execution_context` with a `fiber`.<br><br>That's what=
option #3 does: provide an identifier for an `execution_context`, so that =
you can associate objects with it.<br><br>I don't know of a way to do t=
hat without explicit support from `execution_context`. After all, getting t=
he address of a handle type means nothing relative to the object being refe=
renced by the handle.<br><br>Also, Boost.Coroutine2 isn't an answer. De=
spite its claims to the contrary, it implement symmetric coroutines. Just l=
ook at <a href=3D"http://www.boost.org/doc/libs/1_59_0/libs/coroutine2/doc/=
html/coroutine2/coroutine/asymmetric.html">all of the examples in the docum=
entation</a>: they're not asymmetric at all. All of them are resuming a=
<i>specific</i> coroutine. Not one of them yields execution directly to it=
s caller without being explicitly told which coroutine it should yield to. =
They're generating values for a specific execution context, or retrievi=
ng values <i>from</i> a specific execution context. Boost.Coroutine2 is all=
about getting values from Boost.Context's symmetric coroutines.<br><br=
>The point of an asymmetric coroutine is that you <i>don't know</i> who=
your caller is. And you don't care. You could be executed from one con=
text one time, then resumed from another context later. You don't care =
which it is; you just want to yield back to whomever it was that started yo=
u.<br><br>Boost.Coroutine2 does not provide this. Well, not without passing=
a specific object up the callstack to whomever yields (and quite frankly, =
I can do that with `execution_context`).<br><br>Remember: we want stackful =
coroutines precisely because we want to be able to yield anywhere. So we ma=
y be very far from that lambda, and we absolutely do not want to have to pa=
ss the context to yield to through every single function along the way.<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_618_1426928661.1444667559849--
------=_Part_617_873234289.1444667559848--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Mon, 12 Oct 2015 09:59:20 -0700 (PDT)
Raw View
------=_Part_669_925974911.1444669160767
Content-Type: multipart/alternative;
boundary="----=_Part_670_1334575416.1444669160767"
------=_Part_670_1334575416.1444669160767
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 5:32:40 PM UTC+1, Nicol Bolas wrote:
>
> On Monday, October 12, 2015 at 1:18:34 AM UTC-4, Gor Nishanov wrote:
>>
>> Hmm... I think you can take execution_context as proposed in p0099 and=
=20
>> build a higher level abstraction on top without losing any efficiency.
>>
>
> None of the options I've suggested involves any loss of efficiency (even=
=20
> options 1 and 2 are just an extra pointer). The default case is still=20
> symmetric operation; the possibilities I've outlined simply allow for the=
=20
> *chance* to make them asymmetric.
> =20
>
>> Something like this:
>>
>> fiber ctors + swap + assignment + destructor +
>>
>> fiber.join() =E2=80=93 resumes the fiber (remembers the context who call=
ed it)
>>
>> this_fiber::suspend() =E2=80=93 yields back to whomever called it
>>
>
> The first two are easy enough to do. It's the third part that seems=20
> impossible. `execution_context::current` gives you the current=20
> `execution_context`, but how do you convert that into a user-defined type=
?=20
> That is, how do you implement `this_fiber`, given only=20
> `execution_context::current` to work with?
>
current is just a thread_local, which is switched on coroutine fiber. You=
=20
can implement this_fiber in the same way. on resume This_fiber would store=
=20
the calling context internally. this_fiber::yield would simply resume it.
The reason you wouldn't want to do it is another: asymmetric coroutines are=
=20
really useful to implement value yielding generators, and in c++ you would=
=20
want them to be statically type safe. A thread local yield would need to=20
either allow yielding the moral equivalent of boost::any or do a dynamic=20
type check. Neither solution is really ideal.
Really, symmetric coroutines are superior in anyway. What actual use case=
=20
you have in mind that would be fulfilled by asymmetric coroutines?
=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_670_1334575416.1444669160767
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 5:32:40 PM UTC+1, Nicol Bolas 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">On Monday, October 12=
, 2015 at 1:18:34 AM UTC-4, Gor Nishanov 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">Hmm... I think you can take execution_context =
as proposed in p0099 and build a higher level abstraction on top without lo=
sing any efficiency.</div></blockquote><div><br>None of the options I'v=
e suggested involves any loss of efficiency (even options 1 and 2 are just =
an extra pointer). The default case is still symmetric operation; the possi=
bilities I've outlined simply allow for the <i>chance</i> to make them =
asymmetric.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Something like this:</div><div><br></div><div><p class=3D"Mso=
Normal">fiber ctors + swap + assignment + destructor +</p>
<p class=3D"MsoNormal">fiber.join() =E2=80=93 resumes the fiber (remembers =
the context who
called it)</p>
<p class=3D"MsoNormal">this_fiber::suspend() =E2=80=93 yields back to whome=
ver called it</p></div></div></blockquote><div><br>The first two are easy e=
nough to do. It's the third part that seems impossible. `execution_cont=
ext::current` gives you the current `execution_context`, but how do you con=
vert that into a user-defined type? That is, how do you implement `this_fib=
er`, given only `execution_context::current` to work with?<br></div></div><=
/blockquote><div><br>current is just a thread_local, which is switched on c=
oroutine fiber. You can implement this_fiber in the same way. on resume Thi=
s_fiber would store the calling context internally. this_fiber::yield would=
simply resume it.<br><br>The reason you wouldn't want to do it is anot=
her: asymmetric coroutines are really useful to implement value yielding ge=
nerators, and in c++ you would want them to be statically type safe. A thre=
ad local yield would need to either allow yielding the moral equivalent of =
boost::any or do a dynamic type check. Neither solution is really ideal.<br=
><br>Really, symmetric coroutines are superior in anyway. What actual use c=
ase you have in mind that would be fulfilled by asymmetric coroutines?<br>=
=C2=A0</div>-- 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_670_1334575416.1444669160767--
------=_Part_669_925974911.1444669160767--
.
Author: Gor Nishanov <gornishanov@gmail.com>
Date: Mon, 12 Oct 2015 10:00:18 -0700 (PDT)
Raw View
------=_Part_177_1149102097.1444669218643
Content-Type: multipart/alternative;
boundary="----=_Part_178_295887487.1444669218644"
------=_Part_178_295887487.1444669218644
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 9:32:40 AM UTC-7, Nicol Bolas wrote:
>
> On Monday, October 12, 2015 at 1:18:34 AM UTC-4, Gor Nishanov wrote:
>>
>> =20
>>
> Something like this:
>>
>> fiber ctors + swap + assignment + destructor +
>>
>> fiber.join() =E2=80=93 resumes the fiber (remembers the context who call=
ed it)
>>
>> this_fiber::suspend() =E2=80=93 yields back to whomever called it
>>
>
> The first two are easy enough to do. It's the third part that seems=20
> impossible. `execution_context::current` gives you the current=20
> `execution_context`, but how do you convert that into a user-defined type=
?=20
> That is, how do you implement `this_fiber`, given only=20
> `execution_context::current` to work with?
>
thread_local variable tracks the current fiber. That is how=20
this_fiber::suspend() discovers the current fiber.
fiber::join() {
aligned_storage_t<exection_context> buf; // room to store execution=20
context of the current thread
// this thread goes nowhere=20
until a fiber returns from join()
// does not have to be a fiber=
=20
we switched to initially
this->caller_context =3D &buf; // note, this is a current fiber
this->switch_to_self(); // store the current set of register in caller=
=20
context,=20
// loads the fiber ones from its own context
}
fiber::switch_to(fiber other) {
other->caller_context =3D this->caller_context; // transfer the pointer,=
=20
so that suspend knows where to go on suspend()
other->switch_from(this); // stores the current set of register in this=
=20
fiber
// loads its own from the one stored in other
}
this_fiber::suspend() {
tlsCurrentFiber-> SaveCurentExecutionStateInCurrentFiberStore, load=20
registers from the one pointer by caller_context
}
Something like that.
--=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_178_295887487.1444669218644
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, October 12, 2015 at 9:32:40 AM UTC-7, Nicol Bolas wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; paddi=
ng-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px=
; border-left-style: solid;"><div dir=3D"ltr">On Monday, October 12, 2015 a=
t 1:18:34 AM UTC-4, Gor Nishanov wrote:<blockquote class=3D"gmail_quote" st=
yle=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 di=
r=3D"ltr">=C2=A0</div></blockquote><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>Something like this:</div><div><br></div><div><p class=3D"Mso=
Normal">fiber ctors + swap + assignment + destructor +</p>
<p class=3D"MsoNormal">fiber.join() =E2=80=93 resumes the fiber (remembers =
the context who
called it)</p>
<p class=3D"MsoNormal">this_fiber::suspend() =E2=80=93 yields back to whome=
ver called it</p></div></div></blockquote><div><br>The first two are easy e=
nough to do. It's the third part that seems impossible. `execution_cont=
ext::current` gives you the current `execution_context`, but how do you con=
vert that into a user-defined type? That is, how do you implement `this_fib=
er`, given only `execution_context::current` to work with?<br></div></div><=
/blockquote><div><br></div><div>thread_local variable tracks the current fi=
ber. That is how this_fiber::suspend() discovers the current fiber.</div><d=
iv><br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187,=
187, 187); border-image: none; -ms-word-wrap: break-word; background-color=
: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyp=
rint"><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">fib=
er</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0=
);">::</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0=
);">join</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, =
102, 0);">()</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 102, 0);">{</span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(0, 0, 0);"><br>=C2=A0 =C2=A0 aligned_storage_t</span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(0, 136, 0);"><exection_context></sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> buf</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=
;</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(136, 0, 0);">=
// room to store execution context of the current thread</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(136, 0, 0);">//=
this thread goes nowhere until a fiber returns from join()</span><span cla=
ss=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(136, 0, 0);">//=
does not have to be a fiber we switched to initially</span><span class=3D"=
styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 </span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">this</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">=
-></span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0)=
;">caller_context </span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(102, 102, 0);">&</span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(0, 0, 0);">buf</span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(102, 102, 0);">;</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(136, 0, 0);">// note, this is a current fiber</span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =
=C2=A0 </span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, =
136);">this</span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 102, 0);">-></span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(0, 0, 0);">switch_to_self</span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(102, 102, 0);">();</span><span class=3D"styled-by-prettify=
" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(136, 0, 0);">// store the current set of register in c=
aller context, </span><span class=3D"styled-by-prettify" style=3D"color: rg=
b(0, 0, 0);"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span class=3D"styled-by-p=
rettify" style=3D"color: rgb(136, 0, 0);">// loads the fiber ones from its =
own context</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0,=
0, 0);"><br></span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
102, 102, 0);">}</span><span class=3D"styled-by-prettify" style=3D"color: r=
gb(0, 0, 0);"><br><br>fiber</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);">::</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(0, 0, 0);">switch_to</span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(102, 102, 0);">(</span><span class=3D"styled-by-p=
rettify" style=3D"color: rgb(0, 0, 0);">fiber other</span><span class=3D"st=
yled-by-prettify" style=3D"color: rgb(102, 102, 0);">)</span><span class=3D=
"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"=
styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0oth=
er</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0=
);">-></span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 0);">caller_context </span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 136);">this</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(102, 102, 0);">-></span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(0, 0, 0);">caller_context</span><span class=3D"st=
yled-by-prettify" style=3D"color: rgb(102, 102, 0);">;</span><span class=3D=
"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"=
styled-by-prettify" style=3D"color: rgb(136, 0, 0);">// transfer the pointe=
r, so that suspend knows where to go on suspend()</span><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0other</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">->=
;</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">s=
witch_from</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102=
, 102, 0);">(</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 136);">this</span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(102, 102, 0);">);</span><span class=3D"styled-by-prettify" style=3D"col=
or: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(136, 0, 0);">// stores the current set of register in this fiber</sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" st=
yle=3D"color: rgb(136, 0, 0);">// loads its own from the one stored in othe=
r</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><=
br></span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, =
0);">}</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0=
);"><br><br>this_fiber</span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(102, 102, 0);">::</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);">suspend</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(102, 102, 0);">()</span><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0tlsCurrentFiber</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">->=
;</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);=
">SaveCurentExecutionStateInCurrentFiberStore</span><span class=3D"styled-b=
y-prettify" style=3D"color: rgb(102, 102, 0);">,</span><span class=3D"style=
d-by-prettify" style=3D"color: rgb(0, 0, 0);"> load registers </span><span =
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">from</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> the one po=
inter </span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 1=
36);">by</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,=
0);"> caller_context<br></span><span class=3D"styled-by-prettify" style=3D=
"color: rgb(102, 102, 0);">}</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);"><br></span></div></code></div><div><br></div><div=
>Something like that.<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_178_295887487.1444669218644--
------=_Part_177_1149102097.1444669218643--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 12 Oct 2015 10:40:00 -0700 (PDT)
Raw View
------=_Part_765_883830523.1444671600365
Content-Type: multipart/alternative;
boundary="----=_Part_766_2110371986.1444671600365"
------=_Part_766_2110371986.1444671600365
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 12:59:21 PM UTC-4, Giovanni Piero Deretta=20
wrote:
>
> On Monday, October 12, 2015 at 5:32:40 PM UTC+1, Nicol Bolas wrote:
>>
>> On Monday, October 12, 2015 at 1:18:34 AM UTC-4, Gor Nishanov wrote:
>>>
>>> Hmm... I think you can take execution_context as proposed in p0099 and=
=20
>>> build a higher level abstraction on top without losing any efficiency.
>>>
>>
>> None of the options I've suggested involves any loss of efficiency (even=
=20
>> options 1 and 2 are just an extra pointer). The default case is still=20
>> symmetric operation; the possibilities I've outlined simply allow for th=
e=20
>> *chance* to make them asymmetric.
>> =20
>>
>>> Something like this:
>>>
>>> fiber ctors + swap + assignment + destructor +
>>>
>>> fiber.join() =E2=80=93 resumes the fiber (remembers the context who cal=
led it)
>>>
>>> this_fiber::suspend() =E2=80=93 yields back to whomever called it
>>>
>>
>> The first two are easy enough to do. It's the third part that seems=20
>> impossible. `execution_context::current` gives you the current=20
>> `execution_context`, but how do you convert that into a user-defined typ=
e?=20
>> That is, how do you implement `this_fiber`, given only=20
>> `execution_context::current` to work with?
>>
>
> current is just a thread_local, which is switched on coroutine fiber. You=
=20
> can implement this_fiber in the same way. on resume This_fiber would stor=
e=20
> the calling context internally. this_fiber::yield would simply resume it.
>
There's a problem here. It's about how that thread_local gets updated.
With `execution_context`, it's easy. If the value is NULL, then that's the=
=20
first time `current` has been called on that thread. So it creates an=20
`execution_context` that represents that path of execution. Anytime the=20
user resumes an execution context, the thread_local is updated accordingly.
The problem with fibers mirroring that process is this.
All threads start on an execution context which is not a fiber (even if=20
your thread function immediately starts a fiber, there is an execution=20
context under it that is not a fiber). If you start up fiber1 on that=20
context, then the thread_local gets filled in with fiber1, and fiber1's=20
parent context is updated.
Now, let's say that fiber1 decides that it needs to do some fiber=20
processing of its own. So it starts up fiber2. When it does so, it's parent=
=20
context becomes fiber1, and the thread_local is updated to be fiber2.=20
That's fine.
What happens if fiber2 yields? The thread_local stores fiber2, so it can=20
get at the parent execution context and resumes it. But what happens to the=
=20
thread_local variable?
Because fiber2 was executed from a fiber, the thread_local needs to be set=
=20
to that fiber. But... we have no way of knowing that fiber2 *was* launched=
=20
from a fiber. And there's no reason to assume that it was. There is no way=
=20
to convert an execution_context into a fiber, remember? So there's no way=
=20
to even test that.
And there is no reason why fibers should be prohibited from starting fibers=
=20
of their own, or from starting non-fiber contexts that *themselves* start=
=20
fibers of their own.
So long as there is no way to transform an execution_context into a fiber=
=20
(if it is indeed from a fiber), then merely having a thread_local will not=
=20
help you.
Just give us a pointer already. It costs *nothing*. There is no reason not=
=20
to do it.
=20
> The reason you wouldn't want to do it is another: asymmetric coroutines=
=20
> are really useful to implement value yielding generators, and in c++ you=
=20
> would want them to be statically type safe. A thread local yield would ne=
ed=20
> to either allow yielding the moral equivalent of boost::any or do a dynam=
ic=20
> type check. Neither solution is really ideal.
>
=20
>
Really, symmetric coroutines are superior in anyway. What actual use case=
=20
> you have in mind that would be fulfilled by asymmetric coroutines?
>
I have a function. Its process of execution will take multiple iterations=
=20
of the main program's loop. I don't want to start up a thread or anything=
=20
for it. I want it to execute at a specific time and place in the loop, but=
=20
I want it to be able to wait on things that will happen many loops from now=
..
There are no "values" to be "yielded" (or at least, not in that sense).=20
This could be anything from a scene animation system in a videogame to=20
animating the positions of a GUI in motion (moving a widget from one=20
location to another to another, in a sequence). Asymmetric coroutines have=
=20
plenty of uses.
Take the GUI-in-motion example. Normally, you'd have to code this in a very=
=20
weird way. With asymmetric coroutines, it looks like this:
{
auto anim =3D widget->AnimateMoveTo(location1);
while(!anim)
coroutine::yield();
}
{
auto anim =3D widget->AnimateMoveTo(location2);
auto anim2 =3D widget2->AnimateMoveTo(location3);
while(!anim && !anim2)
coroutine::yield();
}
That code is extremely easy to read, understand, reason about, modify, and=
=20
maintain. No threading, synchronization, or anything else needs to be=20
involved.
I don't want Boost.Coroutine2 and its not-at-all-asymmetric coroutines. I=
=20
don't want Boost.Fiber and its scheduler. I just want a function that=20
executes for a bit, then returns. When it's done, it's done. At the end of=
=20
the day, it's a very simple concept.
The fact that many other languages offer asymmetric coroutines should at=20
least prove their utility. Not all coroutines sit there and wait on other=
=20
coroutines.
--=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_766_2110371986.1444671600365
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, October 12, 2015 at 12:59:21 PM UTC-4, Giovanni Piero Deretta wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex=
;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday, October 12, 201=
5 at 5:32:40 PM UTC+1, 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">On Monday, October 12, 2015 at 1:18:34 AM UTC-4, Gor=
Nishanov wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-=
left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Hm=
m... I think you can take execution_context as proposed in p0099 and build =
a higher level abstraction on top without losing any efficiency.</div></blo=
ckquote><div><br>None of the options I've suggested involves any loss o=
f efficiency (even options 1 and 2 are just an extra pointer). The default =
case is still symmetric operation; the possibilities I've outlined simp=
ly allow for the <i>chance</i> to make them asymmetric.<br>=C2=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Something like th=
is:</div><div><br></div><div><p class=3D"MsoNormal">fiber ctors + swap + as=
signment + destructor +</p>
<p class=3D"MsoNormal">fiber.join() =E2=80=93 resumes the fiber (remembers =
the context who
called it)</p>
<p class=3D"MsoNormal">this_fiber::suspend() =E2=80=93 yields back to whome=
ver called it</p></div></div></blockquote><div><br>The first two are easy e=
nough to do. It's the third part that seems impossible. `execution_cont=
ext::current` gives you the current `execution_context`, but how do you con=
vert that into a user-defined type? That is, how do you implement `this_fib=
er`, given only `execution_context::current` to work with?<br></div></div><=
/blockquote><div><br>current is just a thread_local, which is switched on c=
oroutine fiber. You can implement this_fiber in the same way. on resume Thi=
s_fiber would store the calling context internally. this_fiber::yield would=
simply resume it.<br></div></blockquote><div><br>There's a problem her=
e. It's about how that thread_local gets updated.<br><br>With `executio=
n_context`, it's easy. If the value is NULL, then that's the first =
time `current` has been called on that thread. So it creates an `execution_=
context` that represents that path of execution. Anytime the user resumes a=
n execution context, the thread_local is updated accordingly.<br><br>The pr=
oblem with fibers mirroring that process is this.<br><br>All threads start =
on an execution context which is not a fiber (even if your thread function =
immediately starts a fiber, there is an execution context under it that is =
not a fiber). If you start up fiber1 on that context, then the thread_local=
gets filled in with fiber1, and fiber1's parent context is updated.<br=
><br>Now, let's say that fiber1 decides that it needs to do some fiber =
processing of its own. So it starts up fiber2. When it does so, it's pa=
rent context becomes fiber1, and the thread_local is updated to be fiber2. =
That's fine.<br><br>What happens if fiber2 yields? The thread_local sto=
res fiber2, so it can get at the parent execution context and resumes it. B=
ut what happens to the thread_local variable?<br><br>Because fiber2 was exe=
cuted from a fiber, the thread_local needs to be set to that fiber. But... =
we have no way of knowing that fiber2 <i>was</i> launched from a fiber. And=
there's no reason to assume that it was. There is no way to convert an=
execution_context into a fiber, remember? So there's no way to even te=
st that.<br><br>And there is no reason why fibers should be prohibited from=
starting fibers of their own, or from starting non-fiber contexts that <i>=
themselves</i> start fibers of their own.<br><br>So long as there is no way=
to transform an execution_context into a fiber (if it is indeed from a fib=
er), then merely having a thread_local will not help you.<br><br>Just give =
us a pointer already. It costs <i>nothing</i>. There is no reason not to do=
it.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>The r=
eason you wouldn't want to do it is another: asymmetric coroutines are =
really useful to implement value yielding generators, and in c++ you would =
want them to be statically type safe. A thread local yield would need to ei=
ther allow yielding the moral equivalent of boost::any or do a dynamic type=
check. Neither solution is really ideal.<br></div></blockquote><blockquote=
style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 2=
04); padding-left: 1ex;" class=3D"gmail_quote"><div>=C2=A0</div></blockquot=
e><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div>Really, symmetric corou=
tines are superior in anyway. What actual use case you have in mind that wo=
uld be fulfilled by asymmetric coroutines?<br></div></blockquote><br>I have=
a function. Its process of execution will take multiple iterations of the =
main program's loop. I don't want to start up a thread or anything =
for it. I want it to execute at a specific time and place in the loop, but =
I want it to be able to wait on things that will happen many loops from now=
..<br><br>There are no "values" to be "yielded" (or at l=
east, not in that sense). This could be anything from a scene animation sys=
tem in a videogame to animating the positions of a GUI in motion (moving a =
widget from one location to another to another, in a sequence). Asymmetric =
coroutines have plenty of uses.<br><br>Take the GUI-in-motion example. Norm=
ally, you'd have to code this in a very weird way. With asymmetric coro=
utines, it looks like this:<br><br><div class=3D"prettyprint" style=3D"back=
ground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-=
style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pre=
ttyprint"><div class=3D"subprettyprint"><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 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> anim </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
widget</span><span style=3D"color: #660;" class=3D"styled-by-prettify">->=
;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">AnimateMo=
veTo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">location1</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">while</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(!</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">anim</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 coroutine</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">yield</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br><br></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 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">aut=
o</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> anim </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> widget</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">-></span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">AnimateMoveTo</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">location2</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> anim2 </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> widget2</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">-></span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">AnimateMoveTo</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">location3</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">whi=
le</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(!</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">anim </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&&</span><spa=
n 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">anim2</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 coroutine</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">yield</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span></div></code></div><br>That code is extremely easy to read=
, understand, reason about, modify, and maintain. No threading, synchroniza=
tion, or anything else needs to be involved.<br><br>I don't want Boost.=
Coroutine2 and its not-at-all-asymmetric coroutines. I don't want Boost=
..Fiber and its scheduler. I just want a function that executes for a bit, t=
hen returns. When it's done, it's done. At the end of the day, it&#=
39;s a very simple concept.<br><br>The fact that many other languages offer=
asymmetric coroutines should at least prove their utility. Not all corouti=
nes sit there and wait on other coroutines.<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_766_2110371986.1444671600365--
------=_Part_765_883830523.1444671600365--
.