220 21621 <22794062-fc04-4458-bc5d-fc32d1466609@isocpp.org> article
Path: news.gmane.org!not-for-mail
From: Nicol Bolas <jmckesson@gmail.com>
Newsgroups: gmane.comp.lang.c++.isocpp.proposals
Subject: Re: Re: P0099 suggestion: Minimal support for
 asymmetric suspend/resume
Date: Mon, 12 Oct 2015 13:27:30 -0700 (PDT)
Lines: 506
Approved: news@gmane.org
Message-ID: <22794062-fc04-4458-bc5d-fc32d1466609@isocpp.org>
References: <f3965f07-5e1a-49c7-87e4-5ba7f93d09e5@isocpp.org>
 <dafc4ddf-8897-445b-afef-b366e0fb6bf2@isocpp.org> <a1c097ac-b96b-48ef-b37a-c289400b300b@isocpp.org>
 <cb31a5ea-fd66-4ea1-9f66-84b6cc9d3a8c@isocpp.org> <0a976368-64bd-47cd-b276-36ad5db6c2c9@isocpp.org>
 <ba4c8f2e-eba9-4f5d-9c94-59891509a8a1@isocpp.org>
 <CA+wfc1_xzwSf98Jjx=Trv_0Xq7GLmKktY3O+bYFvq+n0+Cjn+A@mail.gmail.com>
Reply-To: std-proposals@isocpp.org
NNTP-Posting-Host: plane.gmane.org
Mime-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_5050_1863004027.1444681650356"
X-Trace: ger.gmane.org 1444681658 5613 80.91.229.3 (12 Oct 2015 20:27:38 GMT)
X-Complaints-To: usenet@ger.gmane.org
NNTP-Posting-Date: Mon, 12 Oct 2015 20:27:38 +0000 (UTC)
To: ISO C++ Standard - Future Proposals <std-proposals@isocpp.org>
Original-X-From: std-proposals+bncBCEKFTV6ZUMBBM5P6CYAKGQEVSWHADI@isocpp.org Mon Oct 12 22:27:38 2015
Return-path: <std-proposals+bncBCEKFTV6ZUMBBM5P6CYAKGQEVSWHADI@isocpp.org>
Envelope-to: gclcip-std-proposals@m.gmane.org
Original-Received: from mail-pa0-f70.google.com ([209.85.220.70])
	by plane.gmane.org with esmtp (Exim 4.69)
	(envelope-from <std-proposals+bncBCEKFTV6ZUMBBM5P6CYAKGQEVSWHADI@isocpp.org>)
	id 1Zljgz-0003PE-1C
	for gclcip-std-proposals@m.gmane.org; Mon, 12 Oct 2015 22:27:33 +0200
Original-Received: by pacex11 with SMTP id ex11sf322149128pac.2
        for <gclcip-std-proposals@m.gmane.org>; Mon, 12 Oct 2015 13:27:32 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=20120113;
        h=date:from:to:message-id:in-reply-to:references:subject:mime-version
         :content-type:x-original-sender:reply-to:precedence:mailing-list
         :list-id:x-spam-checked-in-group:list-post:list-help:list-archive
         :list-subscribe:list-unsubscribe;
        bh=l3AYmmWOjy6yOHylvQeRkj1dbogL1H9gBJvZLQZd5C8=;
        b=GdUnTbHnce/nH7Xk1m2ONR3pvcyD13sjSW4KqyQRDu9x5zbfPuYrwwnlsJm5+V9iqn
         tW8Jxh8I9G+/eBkK1R0i6hgE0m/AA2JwpXA6lgVbG09zRfp33EV/qbiTcczjO7fPKyir
         rT4h8nxur23scQGyJrEN/qU5rUYIMcBkvTMu/lKzE7RfdgIH5ZsEHtWwoPuaOq/8Mc5i
         OUvjd2ppaOC3sec5ygZ0YgOqUku7iTf6T9RioYUn275GpQx+RT4sANlDe3w8z96klH24
         9t+ImT/OZxu16hao/ugZf2QTTGhuqVClTblmhvoq67SRG2pG+02x1JpBAZ8fNhAdOtWk
         tUTg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=1e100.net; s=20130820;
        h=x-gm-message-state:date:from:to:message-id:in-reply-to:references
         :subject:mime-version:content-type:x-original-sender:reply-to
         :precedence:mailing-list:list-id:x-spam-checked-in-group:list-post
         :list-help:list-archive:list-subscribe:list-unsubscribe;
        bh=l3AYmmWOjy6yOHylvQeRkj1dbogL1H9gBJvZLQZd5C8=;
        b=Ae9fEWKmbcqvPmexbGw5GPeR6oviYBCONJwXJyBxZfp8becrGzHcz6Zi7terLEMF+4
         PPXVmbdWtZ4K+TrW2w8vCAbVmc8klGGJELTo0vbII1jTR/n6JrnDtPPKD/H2pbvdAyli
         WL8L/u/+As8SnIfX7otHbfTfQh/O0OCWknD9y6wNj/S2pTSrlAzftF4MvpI414f+BR8P
         vp8OpJu9ONGVXjCkpprP26jOfo01vHy2M44Uz4Zh+/AcmZVXQOVxM/6CGFqPdhQz9FEg
         E/+TQ1sq/ahr+FKQ6XmXTapip/qKXJqGZt7s8ytziFwQfGQ4l61sEBnxcxlKiaEX8HWJ
         zcFQ==
X-Gm-Message-State: ALoCoQnv0e7t/AGC4kcFflT0Rwb887uBBzZ6L+R9VOgrDwcKiyDLNCeNwjK5mV4PV/wWnfB280We
X-Received: by 10.68.176.132 with SMTP id ci4mr6656152pbc.13.1444681652093;
        Mon, 12 Oct 2015 13:27:32 -0700 (PDT)
X-BeenThere: std-proposals@isocpp.org
Original-Received: by 10.107.4.199 with SMTP id 190ls1481620ioe.16.gmail; Mon, 12 Oct
 2015 13:27:31 -0700 (PDT)
X-Received: by 10.50.131.164 with SMTP id on4mr161030igb.8.1444681651223;
        Mon, 12 Oct 2015 13:27:31 -0700 (PDT)
In-Reply-To: <CA+wfc1_xzwSf98Jjx=Trv_0Xq7GLmKktY3O+bYFvq+n0+Cjn+A@mail.gmail.com>
X-Original-Sender: jmckesson@gmail.com
Precedence: list
Mailing-list: list std-proposals@isocpp.org; contact std-proposals+owners@isocpp.org
List-ID: <std-proposals.isocpp.org>
X-Spam-Checked-In-Group: std-proposals@isocpp.org
X-Google-Group-Id: 399137483710
List-Post: <http://groups.google.com/a/isocpp.org/group/std-proposals/post>, <mailto:std-proposals@isocpp.org>
List-Help: <http://support.google.com/a/isocpp.org/bin/topic.py?topic=25838>, <mailto:std-proposals+help@isocpp.org>
List-Archive: <http://groups.google.com/a/isocpp.org/group/std-proposals/>
List-Subscribe: <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>,
 <mailto:std-proposals+subscribe@isocpp.org>
List-Unsubscribe: <mailto:googlegroups-manage+399137483710+unsubscribe@googlegroups.com>,
 <http://groups.google.com/a/isocpp.org/group/std-proposals/subscribe>
Xref: news.gmane.org gmane.comp.lang.c++.isocpp.proposals:21621
Archived-At: <http://permalink.gmane.org/gmane.comp.lang.c++.isocpp.proposals/21621>

------=_Part_5050_1863004027.1444681650356
Content-Type: multipart/alternative; 
	boundary="----=_Part_5051_270390137.1444681650357"

------=_Part_5051_270390137.1444681650357
Content-Type: text/plain; charset=UTF-8

On Monday, October 12, 2015 at 2:08:10 PM UTC-4, Oliver Kowalke wrote:
>
> 2015-10-12 19:40 GMT+02:00 Nicol Bolas <jmck...@gmail.com <javascript:>>:
>
> With `execution_context`, it's easy. If the value is NULL, then that's the 
>> first time `current` has been called on that thread. 
>>
>
> it is not NULL - the main thread or any other thread represents an 
> execution-context
>  
>
>> 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).
>>
>
> you have to understand that a fiber or a stackful coroutine can be 
> represented by one or two execution_contexts
> in the case of fibers the main-thread can be tracked as fiber (main-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.
>> 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 parent 
>> context becomes fiber1, and the thread_local is updated to be fiber2. 
>> That's fine.
>> What happens if fiber2 yields? The thread_local stores fiber2, so it can 
>> get at the parent execution context and resumes it. But what happens to the 
>> thread_local variable?
>>
>
> - fibers are agnostic of their predecessor and successor 
> - a fiber can not yield, a fiber uses symmetric context switching - 
> symmetric context switching requires that a target is given to the switch 
> operation
>

OK, the entire rest of your post is based on what may be a misuse of 
terminology on my part. When I said "fiber", what I meant was "the 
construct giving me the functionality I asked for". I based this on Gor's 
use of the term; I assumed that when he said "fiber", he meant something 
that gave me the functionality I was asking for, and he described it as 
such.

Whether that matches your definition of what a "fiber" is or not (since the 
definition of these terms is far from universal), I can't say.

Therefore, forget everything I said. So that we are all clear on what words 
mean, I will define the term *fully asymetric coroutine* as follows:

*A stackful coroutine that can halt its execution, returning control to 
whichever execution context resumed it.*

That is the behavior I want to be able to build atop `execution_context`. 
So here's what I said again, using proper terminology:

----

There's a problem here. It's about how that thread_local gets updated.

With `execution_context`, it's easy. Initially, its an `execution_context` 
that represents the initial path of execution for the thread. Anytime the 
user resumes an execution context, the thread_local is updated accordingly.

The problem with fa_coroutine (the prospective type implementing a fully 
asymetric coroutine atop an `execution_context`) mirroring that process is 
this.

All threads start on an execution context which is not a fa_coroutine (even 
if your thread function immediately starts a fa_coroutine, there is an 
execution context under it that is not a fa_coroutine). So the thread_local 
must be empty. If you start up fa_co1 on that context, then the 
thread_local gets filled in with fa_co1, and fa_co1's parent context is 
updated.

Now, let's say that fa_co1 decides that it needs to do some fa_coroutine 
processing of its own. So it starts up fa_co2. When it does so, its parent 
context becomes fa_co1, and the thread_local is updated to be fa_co2. 
That's fine.

What happens when fa_co2 yields? The thread_local stores fa_co2, so it can 
get at the parent execution context and resumes it. But what happens to the 
thread_local variable?

Because fa_co2 was executed from a fa_coroutine, when you return, the 
thread_local needs to be set to that fa_co. But... we have no way of 
knowing that fa_co2 was launched from a fa_coroutine. And there's no reason 
to assume that it was. There is no way to convert an execution_context into 
a fa_coroutine, remember? So there's no way to even test that.

And there is no reason why fa_coroutines should be prohibited from starting 
fa_coroutines of their own, or from starting non-fa_coroutine contexts that 
themselves start fa_coroutines of their own.

So long as there is no way to transform an execution_context into a 
fa_coroutine (if it is indeed from a fa_coroutine), then merely having a 
thread_local will not help you.

----

I believe this can be resolved, though it requires some effort:

class fa_coroutine
{
    //The caller can be either a naked execution_context or another 
fa_coroutine.
    //Ignore the fact that this isn't legal. You get the general idea.
    std::variant<execution_context, fa_coroutine> caller;
    std::aligned_storage_t<sizeof(execution_context), alignof(
execution_context) ec_data;

    execution_context *get_context() {return static_cast<execution_context>(
ec_data);}

    static thread_local std::optional<fa_coroutine> current_fa_co;

public:
    //copying, construction, etc as expected.

    void operator()()
    {
        if(current_fa_co)
            caller = *current_fa_co
        else
            caller = execution_context::current();
        
        current_fa_co = *this;
        get_context()();
    }

    struct update_current_fac
    {
        execution_context operator()(execution_context caller)
        {
            current_fa_co = nullopt;
            return caller;
        }
        
        execution_context operator()(fa_coroutine caller)
        {
            //The caller's caller may be a fa_coroutine or not. The
            //current fa_coroutine must be updated to match.
            fa_coroutine *new_caller = get<fa_coroutine>(&caller.caller)
            if(new_caller)
                current_fa_co = *new_caller
            else
                current_fa_co = nullopt;
                
            //Deliberately bypass fa_coroutine's operator().
            return *caller.get_context()
        }
    }
    
    static void yield_current()
    {
        Expects(current_fa_co);
        execution_context ec = visit(current_fa_co->caller,
            update_current_fac);
        ec(); //Actual yield.
    }
    
    friend struct update_current_fac;
};

-- 

--- 
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_5051_270390137.1444681650357
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Monday, October 12, 2015 at 2:08:10 PM UTC-4, Oliver Kowalke wrote:<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 class=3D=
"gmail_quote">2015-10-12 19:40 GMT+02:00 Nicol Bolas <span dir=3D"ltr">&lt;=
<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"enw4AYkH=
DgAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#39;;ret=
urn true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;">jmck.=
...@gmail.com</a>&gt;</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><div>With `execution_context`, it&#39;s easy. If the value is NULL, th=
en that&#39;s the first time `current` has been called on that thread. </di=
v></blockquote><div><br></div><div>it is not NULL - the main thread or any =
other thread represents an execution-context<br></div><div>=C2=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div>All threads start on an execution context w=
hich is not a fiber (even if your thread function immediately starts a fibe=
r, there is an execution context under it that is not a fiber).</div></bloc=
kquote><div><br></div><div>you have to understand that a fiber or a stackfu=
l coroutine can be represented by one or two execution_contexts<br></div><d=
iv>in the case of fibers the main-thread can be tracked as fiber (main-fibe=
r)<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div> If you st=
art up fiber1 on that context, then the thread_local gets filled in with fi=
ber1, and fiber1&#39;s parent context is updated.<br>Now, let&#39;s say tha=
t fiber1 decides that it needs to do some fiber processing of its own. So i=
t starts up fiber2. When it does so, it&#39;s parent context becomes fiber1=
, and the thread_local is updated to be fiber2. That&#39;s fine.<br>What ha=
ppens if fiber2 yields? The thread_local stores fiber2, so it can get at th=
e parent execution context and resumes it. But what happens to the thread_l=
ocal variable?<br></div></blockquote><div><br></div><div>- fibers are agnos=
tic of their predecessor and successor <br></div><div>- a fiber can not yie=
ld, a fiber uses symmetric context switching - symmetric context switching =
requires that a target is given to the switch operation<br></div></div></di=
v></div></blockquote><div><br>OK, the entire rest of your post is based on =
what may be a misuse of terminology on my part. When I said &quot;fiber&quo=
t;, what I meant was &quot;the construct giving me the functionality I aske=
d for&quot;. I based this on Gor&#39;s use of the term; I assumed that when=
 he said &quot;fiber&quot;, he meant something that gave me the functionali=
ty I was asking for, and he described it as such.<br><br>Whether that match=
es your definition of what a &quot;fiber&quot; is or not (since the definit=
ion of these terms is far from universal), I can&#39;t say.<br><br>Therefor=
e, forget everything I said. So that we are all clear on what words mean, I=
 will define the term <u>fully asymetric coroutine</u> as follows:<br><br><=
u>A stackful coroutine that can halt its execution, returning control to wh=
ichever execution context resumed it.</u><br><br>That is the behavior I wan=
t to be able to build atop `execution_context`. So here&#39;s what I said a=
gain, using proper terminology:<br><br>----<br><br>There&#39;s a problem he=
re. It&#39;s about how that thread_local gets updated.<br><br>With `executi=
on_context`, it&#39;s easy. Initially, its an `execution_context` that repr=
esents the initial path of execution for the thread. Anytime the user resum=
es an execution context, the thread_local is updated accordingly.<br><br>Th=
e problem with fa_coroutine (the prospective type implementing a fully asym=
etric coroutine atop an `execution_context`) mirroring that process is this=
..<br><br>All threads start on an execution context which is not a fa_corout=
ine (even if your thread function immediately starts a fa_coroutine, there =
is an execution context under it that is not a fa_coroutine). So the thread=
_local must be empty. If you start up fa_co1 on that context, then the thre=
ad_local gets filled in with fa_co1, and fa_co1&#39;s parent context is upd=
ated.<br><br>Now, let&#39;s say that fa_co1 decides that it needs to do som=
e fa_coroutine processing of its own. So it starts up fa_co2. When it does =
so, its parent context becomes fa_co1, and the thread_local is updated to b=
e fa_co2. That&#39;s fine.<br><br>What happens when fa_co2 yields? The thre=
ad_local stores fa_co2, so it can get at the parent execution context and r=
esumes it. But what happens to the thread_local variable?<br><br>Because fa=
_co2 was executed from a fa_coroutine, when you return, the thread_local ne=
eds to be set to that fa_co. But... we have no way of knowing that fa_co2 w=
as launched from a fa_coroutine. And there&#39;s no reason to assume that i=
t was. There is no way to convert an execution_context into a fa_coroutine,=
 remember? So there&#39;s no way to even test that.<br><br>And there is no =
reason why fa_coroutines should be prohibited from starting fa_coroutines o=
f their own, or from starting non-fa_coroutine contexts that themselves sta=
rt fa_coroutines of their own.<br><br>So long as there is no way to transfo=
rm an execution_context into a fa_coroutine (if it is indeed from a fa_coro=
utine), then merely having a thread_local will not help you.<br><br>----<br=
><br>I believe this can be resolved, though it requires some effort:<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; w=
ord-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyp=
rint"><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> fa_coroutine<br=
></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: #800;" class=3D"styled-by-prettify">//The call=
er can be either a naked execution_context or another fa_coroutine.</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">//Ignore t=
he fact that this isn&#39;t legal. You get the general idea.</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 std</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify">variant</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">execution_context</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> fa_coroutine</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">caller</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">aligned_storage_t</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">sizeof</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">execution_context</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: #008;" class=3D"styled-by-prettify=
">alignof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">execution_=
context</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ec_data</sp=
an><span 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 e=
xecution_context </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">*</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ge=
t_context</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: #008;" class=3D"styled-by-prettify">return</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">static_cast</span><span style=3D"color: =
#080;" class=3D"styled-by-prettify">&lt;execution_context&gt;</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">ec_data</span><span style=3D"colo=
r: #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">static</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> thread_local std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">optional</span><span style=3D"color:=
 #080;" class=3D"styled-by-prettify">&lt;fa_coroutine&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> current_fa_co</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><br></span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">public</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">//copying, construction, etc as expected=
..</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-pretti=
fy">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</s=
pan><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 <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an 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-pretti=
fy">if</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">current_fa_co=
</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 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">caller</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">current_fa_co<br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">else</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">caller</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> execution_context</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">current</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 current_fa_co </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">*</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">this</span><sp=
an 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 get_context</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">()();</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-pr=
ettify">}</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">struct</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> update_current_fac<br>=C2=A0 =C2=A0 </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 execution_context =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">()(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">execution_context <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">caller</spa=
n><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 =C2=A0 =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 =C2=A0 =C2=A0 =C2=A0 =C2=A0 current_fa_co </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> nullopt</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 =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"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">caller</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 =C2=A0 =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 =C2=A0 =C2=A0=
 <br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 execution_context </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">()(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">fa_coroutine </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">caller</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: #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 =C2=
=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by-prettify"=
>//The caller&#39;s caller may be a fa_coroutine or not. The</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"styled-by=
-prettify">//current fa_coroutine must be updated to match.</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 fa_coroutine </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">*</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">new_caller </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
get</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&lt;fa_=
coroutine&gt;</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(&amp;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">c=
aller</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">caller</span><=
span 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 =C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">if</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">new_ca=
ller</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 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 current_fa_co </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">*</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">new_caller<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">els=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 current_fa_co </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> nullopt</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 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 <br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </sp=
an><span style=3D"color: #800;" class=3D"styled-by-prettify">//Deliberately=
 bypass fa_coroutine&#39;s operator().</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">caller</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">get_context</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: #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 <br>=C2=A0 =C2=A0 <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">static</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> yield_current</span><span s=
tyle=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 s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Expects</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">current_fa_co</span><sp=
an 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 execution_context ec </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> visit</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">curre=
nt_fa_co</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&=
gt;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">caller<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 update_current_fac</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ec</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">//Actual yield.</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </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>=C2=A0 =C2=A0 <br>=C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">friend=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> update_current_fac</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</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></code></div>=
<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&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_5051_270390137.1444681650357--
------=_Part_5050_1863004027.1444681650356--

.
