1<html> 2<head> 3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 4<title>Context switching with call/cc</title> 5<link rel="stylesheet" href="../../../../../doc/src/boostbook.css" type="text/css"> 6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 7<link rel="home" href="../index.html" title="Chapter 1. Context"> 8<link rel="up" href="../index.html" title="Chapter 1. Context"> 9<link rel="prev" href="ff/class__fiber_.html" title="Class fiber"> 10<link rel="next" href="cc/implementations__fcontext_t__ucontext_t_and_winfiber.html" title="Implementations: fcontext_t, ucontext_t and WinFiber"> 11</head> 12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 13<table cellpadding="2" width="100%"><tr> 14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td> 15<td align="center"><a href="../../../../../index.html">Home</a></td> 16<td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td> 17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 19<td align="center"><a href="../../../../../more/index.htm">More</a></td> 20</tr></table> 21<hr> 22<div class="spirit-nav"> 23<a accesskey="p" href="ff/class__fiber_.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="cc/implementations__fcontext_t__ucontext_t_and_winfiber.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> 24</div> 25<div class="section"> 26<div class="titlepage"><div><div><h2 class="title" style="clear: both"> 27<a name="context.cc"></a><a name="cc"></a><a class="link" href="cc.html" title="Context switching with call/cc">Context switching with call/cc</a> 28</h2></div></div></div> 29<div class="toc"><dl class="toc"> 30<dt><span class="section"><a href="cc/implementations__fcontext_t__ucontext_t_and_winfiber.html">Implementations: 31 fcontext_t, ucontext_t and WinFiber</a></span></dt> 32<dt><span class="section"><a href="cc/class__continuation_.html">Class <code class="computeroutput"><span class="identifier">continuation</span></code></a></span></dt> 33</dl></div> 34<div class="note"><table border="0" summary="Note"> 35<tr> 36<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> 37<th align="left">Note</th> 38</tr> 39<tr><td align="left" valign="top"><p> 40 <span class="emphasis"><em>call/cc</em></span> is the reference implementation of C++ proposal 41 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0534r3.pdf" target="_top">P0534R3: 42 call/cc (call-with-current-continuation): A low-level API for stackful context 43 switching</a>. 44 </p></td></tr> 45</table></div> 46<p> 47 <span class="emphasis"><em>call/cc</em></span> (call with current continuation) is a universal 48 control operator (well-known from the programming language Scheme) that captures 49 the current continuation as a first-class object and pass it as an argument 50 to another continuation. 51 </p> 52<p> 53 A continuation (abstract concept of functional programming languages) represents 54 the state of the control flow of a program at a given point in time. Continuations 55 can be suspended and resumed later in order to change the control flow of a 56 program. 57 </p> 58<p> 59 Modern micro-processors are registers machines; the content of processor registers 60 represent a continuation of the executed program at a given point in time. 61 Operating systems simulate parallel execution of programs on a single processor 62 by switching between programs (context switch) by preserving and restoring 63 the continuation, e.g. the content of all registers. 64 </p> 65<h4> 66<a name="context.cc.h0"></a> 67 <span class="phrase"><a name="context.cc._link_linkend__cc___emphasis_callcc____emphasis___link_"></a></span><a class="link" href="cc.html#context.cc._link_linkend__cc___emphasis_callcc____emphasis___link_"><span class="emphasis"><em>callcc()</em></span></a> 68 </h4> 69<p> 70 <a class="link" href="cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a> is the C++ equivalent 71 to Scheme's <span class="emphasis"><em>call/cc</em></span> operator. It captures the current 72 continuation (the rest of the computation; code after <a class="link" href="cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a>) 73 and triggers a context switch. The context switch is achieved by preserving 74 certain registers (including instruction and stack pointer), defined by the 75 calling convention of the ABI, of the current continuation and restoring those 76 registers of the resumed continuation. The control flow of the resumed continuation 77 continues. The current continuation is suspended and passed as argument to 78 the resumed continuation. 79 </p> 80<p> 81 <a class="link" href="cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a> expects a <span class="emphasis"><em>context-function</em></span> 82 with signature <code class="computeroutput"><span class="char">'continuation(continuation && 83 c)'</span></code>. The parameter <code class="computeroutput"><span class="identifier">c</span></code> 84 represents the current continuation from which this continuation was resumed 85 (e.g. that has called <a class="link" href="cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a>). 86 </p> 87<p> 88 On return the <span class="emphasis"><em>context-function</em></span> of the current continuation 89 has to specify an <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> 90 to which the execution control is transferred after termination of the current 91 continuation. 92 </p> 93<p> 94 If an instance with valid state goes out of scope and the <span class="emphasis"><em>context-function</em></span> 95 has not yet returned, the stack is traversed in order to access the control 96 structure (address stored at the first stack frame) and continuation's stack 97 is deallocated via the <span class="emphasis"><em>StackAllocator</em></span>. 98 </p> 99<div class="note"><table border="0" summary="Note"> 100<tr> 101<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> 102<th align="left">Note</th> 103</tr> 104<tr><td align="left" valign="top"><p> 105 <a class="link" href="stack/segmented.html#segmented"><span class="emphasis"><em>Segmented stacks</em></span></a> are 106 supported by <a class="link" href="cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a> using 107 <a class="link" href="ff/implementations__fcontext_t__ucontext_t_and_winfiber.html#implementation"><span class="emphasis"><em>ucontext_t</em></span></a>. 108 </p></td></tr> 109</table></div> 110<h4> 111<a name="context.cc.h1"></a> 112 <span class="phrase"><a name="context.cc._link_linkend__cc___emphasis_continuation__emphasis___link_"></a></span><a class="link" href="cc.html#context.cc._link_linkend__cc___emphasis_continuation__emphasis___link_"><span class="emphasis"><em>continuation</em></span></a> 113 </h4> 114<p> 115 <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> represents a continuation; 116 it contains the content of preserved registers and manages the associated stack 117 (allocation/deallocation). <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> 118 is a one-shot continuation - it can be used only once, after calling <span class="emphasis"><em>continuation::resume()</em></span> 119 or <span class="emphasis"><em>continuation::resume_with()</em></span> it is invalidated. 120 </p> 121<p> 122 <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> is only move-constructible 123 and move-assignable. 124 </p> 125<p> 126 As a first-class object <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> 127 can be applied to and returned from a function, assigned to a variable or stored 128 in a container. 129 </p> 130<p> 131 A continuation is continued by calling <code class="computeroutput"><span class="identifier">resume</span><span class="special">()</span></code>/<code class="computeroutput"><span class="identifier">resume_with</span><span class="special">()</span></code>. 132 </p> 133<h4> 134<a name="context.cc.h2"></a> 135 <span class="phrase"><a name="context.cc.usage"></a></span><a class="link" href="cc.html#context.cc.usage">Usage</a> 136 </h4> 137<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">context</span><span class="special">;</span> 138<span class="keyword">int</span> <span class="identifier">a</span><span class="special">;</span> 139<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">source</span><span class="special">=</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">callcc</span><span class="special">(</span> 140 <span class="special">[&</span><span class="identifier">a</span><span class="special">](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">sink</span><span class="special">){</span> 141 <span class="identifier">a</span><span class="special">=</span><span class="number">0</span><span class="special">;</span> 142 <span class="keyword">int</span> <span class="identifier">b</span><span class="special">=</span><span class="number">1</span><span class="special">;</span> 143 <span class="keyword">for</span><span class="special">(;;){</span> 144 <span class="identifier">sink</span><span class="special">=</span><span class="identifier">sink</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 145 <span class="keyword">int</span> <span class="identifier">next</span><span class="special">=</span><span class="identifier">a</span><span class="special">+</span><span class="identifier">b</span><span class="special">;</span> 146 <span class="identifier">a</span><span class="special">=</span><span class="identifier">b</span><span class="special">;</span> 147 <span class="identifier">b</span><span class="special">=</span><span class="identifier">next</span><span class="special">;</span> 148 <span class="special">}</span> 149 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">sink</span><span class="special">);</span> 150 <span class="special">});</span> 151<span class="keyword">for</span> <span class="special">(</span><span class="keyword">int</span> <span class="identifier">j</span><span class="special">=</span><span class="number">0</span><span class="special">;</span><span class="identifier">j</span><span class="special"><</span><span class="number">10</span><span class="special">;++</span><span class="identifier">j</span><span class="special">)</span> <span class="special">{</span> 152 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">a</span> <span class="special"><<</span> <span class="string">" "</span><span class="special">;</span> 153 <span class="identifier">source</span><span class="special">=</span><span class="identifier">source</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 154<span class="special">}</span> 155 156<span class="identifier">output</span><span class="special">:</span> 157 <span class="number">0</span> <span class="number">1</span> <span class="number">1</span> <span class="number">2</span> <span class="number">3</span> <span class="number">5</span> <span class="number">8</span> <span class="number">13</span> <span class="number">21</span> <span class="number">34</span> 158</pre> 159<p> 160 This simple example demonstrates the basic usage of <span class="emphasis"><em>call/cc</em></span> 161 as a <span class="emphasis"><em>generator</em></span>. The continuation <code class="computeroutput"><span class="identifier">sink</span></code> 162 represents the <span class="emphasis"><em>main</em></span>-continuation (function <code class="computeroutput"><span class="identifier">main</span><span class="special">()</span></code>). 163 <code class="computeroutput"><span class="identifier">sink</span></code> is captured (current-continuation) 164 by invoking <a class="link" href="cc.html#cc"><span class="emphasis"><em>callcc()</em></span></a> and passed 165 as parameter to the lambda. 166 </p> 167<p> 168 Because the state is invalidated (one-shot continuation) by each call of <span class="emphasis"><em>continuation::resume()</em></span>, 169 the new state of the <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a>, 170 returned by <span class="emphasis"><em>continuation::resume()</em></span>, needs to be assigned 171 to <code class="computeroutput"><span class="identifier">sink</span></code> after each call. 172 </p> 173<p> 174 The lambda that calculates the Fibonacci numbers is executed inside the continuation 175 represented by <code class="computeroutput"><span class="identifier">source</span></code>. Calculated 176 Fibonacci numbers are transferred between the two continuations via variable 177 <code class="computeroutput"><span class="identifier">a</span></code> (lambda capture reference). 178 </p> 179<p> 180 The locale variables <code class="computeroutput"><span class="identifier">b</span></code> and 181 <code class="computeroutput"> <span class="identifier">next</span></code> remain their values during 182 each context switch. This is possible due <code class="computeroutput"><span class="identifier">source</span></code> 183 has its own stack and the stack is exchanged by each context switch. 184 </p> 185<h4> 186<a name="context.cc.h3"></a> 187 <span class="phrase"><a name="context.cc.parameter_passing"></a></span><a class="link" href="cc.html#context.cc.parameter_passing">Parameter 188 passing</a> 189 </h4> 190<p> 191 Data can be transferred between two continuations via global pointers, calling 192 wrappers (like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">bind</span></code>) or lambda captures. 193 </p> 194<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">context</span><span class="special">;</span> 195<span class="keyword">int</span> <span class="identifier">i</span><span class="special">=</span><span class="number">1</span><span class="special">;</span> 196<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">c1</span><span class="special">=</span><span class="identifier">callcc</span><span class="special">([&</span><span class="identifier">i</span><span class="special">](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">c2</span><span class="special">){</span> 197 <span class="identifier">std</span><span class="special">::</span><span class="identifier">printf</span><span class="special">(</span><span class="string">"inside c1,i==%d\n"</span><span class="special">,</span><span class="identifier">i</span><span class="special">);</span> 198 <span class="identifier">i</span><span class="special">+=</span><span class="number">1</span><span class="special">;</span> 199 <span class="keyword">return</span> <span class="identifier">c2</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 200 <span class="special">});</span> 201<span class="identifier">std</span><span class="special">::</span><span class="identifier">printf</span><span class="special">(</span><span class="string">"i==%d\n"</span><span class="special">,</span><span class="identifier">i</span><span class="special">);</span> 202 203<span class="identifier">output</span><span class="special">:</span> 204 <span class="identifier">inside</span> <span class="identifier">c1</span><span class="special">,</span><span class="identifier">i</span><span class="special">==</span><span class="number">1</span> 205 <span class="identifier">i</span><span class="special">==</span><span class="number">2</span> 206</pre> 207<p> 208 <code class="computeroutput"><span class="identifier">callcc</span><span class="special">(<</span><span class="identifier">lambda</span><span class="special">>)</span></code> 209 enters the lambda in continuation represented by <code class="computeroutput"><span class="identifier">c1</span></code> 210 with lambda capture reference <code class="computeroutput"><span class="identifier">i</span><span class="special">=</span><span class="number">1</span></code>. The expression 211 <code class="computeroutput"><span class="identifier">c2</span><span class="special">.</span><span class="identifier">resume</span><span class="special">()</span></code> 212 resumes the continuation <code class="computeroutput"><span class="identifier">c2</span></code>. 213 On return of <code class="computeroutput"><span class="identifier">callcc</span><span class="special">(<</span><span class="identifier">lambda</span><span class="special">>)</span></code>, 214 the variable <code class="computeroutput"><span class="identifier">i</span></code> has the value 215 of <code class="computeroutput"><span class="identifier">i</span><span class="special">+</span><span class="number">1</span></code>. 216 </p> 217<h4> 218<a name="context.cc.h4"></a> 219 <span class="phrase"><a name="context.cc.exception_handling"></a></span><a class="link" href="cc.html#context.cc.exception_handling">Exception 220 handling</a> 221 </h4> 222<p> 223 If the function executed inside a <span class="emphasis"><em>context-function</em></span> emits 224 an exception, the application is terminated by calling <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">terminate</span><span class="special">()</span></code>. <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">exception_ptr</span></code> 225 can be used to transfer exceptions between different continuations. 226 </p> 227<div class="important"><table border="0" summary="Important"> 228<tr> 229<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> 230<th align="left">Important</th> 231</tr> 232<tr><td align="left" valign="top"><p> 233 Do not jump from inside a catch block and then re-throw the exception in 234 another continuation. 235 </p></td></tr> 236</table></div> 237<a name="cc_ontop"></a><h4> 238<a name="context.cc.h5"></a> 239 <span class="phrase"><a name="context.cc.executing_function_on_top_of_a_continuation"></a></span><a class="link" href="cc.html#context.cc.executing_function_on_top_of_a_continuation">Executing 240 function on top of a continuation</a> 241 </h4> 242<p> 243 Sometimes it is useful to execute a new function on top of a resumed continuation. 244 For this purpose <span class="emphasis"><em>continuation::resume_with()</em></span> has to be 245 used. The function passed as argument must accept a rvalue reference to <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> and return <code class="computeroutput"><span class="keyword">void</span></code>. 246 </p> 247<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">context</span><span class="special">;</span> 248<span class="keyword">int</span> <span class="identifier">data</span><span class="special">=</span><span class="number">0</span><span class="special">;</span> 249<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">c</span><span class="special">=</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">callcc</span><span class="special">([&</span><span class="identifier">data</span><span class="special">](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">c</span><span class="special">)</span> <span class="special">{</span> 250 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: entered first time: "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 251 <span class="identifier">data</span><span class="special">+=</span><span class="number">1</span><span class="special">;</span> 252 <span class="identifier">c</span><span class="special">=</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 253 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: entered second time: "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 254 <span class="identifier">data</span><span class="special">+=</span><span class="number">1</span><span class="special">;</span> 255 <span class="identifier">c</span><span class="special">=</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 256 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: entered third time: "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 257 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">c</span><span class="special">);</span> 258 <span class="special">});</span> 259<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: returned first time: "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 260<span class="identifier">data</span><span class="special">+=</span><span class="number">1</span><span class="special">;</span> 261<span class="identifier">c</span><span class="special">=</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 262<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: returned second time: "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 263<span class="identifier">data</span><span class="special">+=</span><span class="number">1</span><span class="special">;</span> 264<span class="identifier">c</span><span class="special">=</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume_with</span><span class="special">([&</span><span class="identifier">data</span><span class="special">](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">c</span><span class="special">){</span> 265 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f2: entered: "</span> <span class="special"><<</span> <span class="identifier">data</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 266 <span class="identifier">data</span><span class="special">=-</span><span class="number">1</span><span class="special">;</span> 267 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span> <span class="identifier">c</span><span class="special">);</span> 268 <span class="special">});</span> 269<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"f1: returned third time"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 270 271<span class="identifier">output</span><span class="special">:</span> 272 <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">entered</span> <span class="identifier">first</span> <span class="identifier">time</span><span class="special">:</span> <span class="number">0</span> 273 <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">returned</span> <span class="identifier">first</span> <span class="identifier">time</span><span class="special">:</span> <span class="number">1</span> 274 <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">entered</span> <span class="identifier">second</span> <span class="identifier">time</span><span class="special">:</span> <span class="number">2</span> 275 <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">returned</span> <span class="identifier">second</span> <span class="identifier">time</span><span class="special">:</span> <span class="number">3</span> 276 <span class="identifier">f2</span><span class="special">:</span> <span class="identifier">entered</span><span class="special">:</span> <span class="number">4</span> 277 <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">entered</span> <span class="identifier">third</span> <span class="identifier">time</span><span class="special">:</span> <span class="special">-</span><span class="number">1</span> 278 <span class="identifier">f1</span><span class="special">:</span> <span class="identifier">returned</span> <span class="identifier">third</span> <span class="identifier">time</span> 279</pre> 280<p> 281 The expression <code class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume_with</span><span class="special">(...)</span></code> 282 executes a lambda on top of continuation <code class="computeroutput"><span class="identifier">c</span></code>, 283 e.g. an additional stack frame is allocated on top of the stack. This lambda 284 assigns <code class="computeroutput"><span class="special">-</span><span class="number">1</span></code> 285 to <code class="computeroutput"><span class="identifier">data</span></code> and returns to the 286 second invocation of <code class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume</span><span class="special">()</span></code>. 287 </p> 288<p> 289 Another option is to execute a function on top of the continuation that throws 290 an exception. 291 </p> 292<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">context</span><span class="special">;</span> 293<span class="keyword">struct</span> <span class="identifier">my_exception</span> <span class="special">:</span> <span class="keyword">public</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span> <span class="special">{</span> 294 <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">c</span><span class="special">;</span> 295 <span class="identifier">my_exception</span><span class="special">(</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">c_</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">what</span><span class="special">)</span> <span class="special">:</span> 296 <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">{</span> <span class="identifier">what</span> <span class="special">},</span> 297 <span class="identifier">c</span><span class="special">{</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span> <span class="identifier">c_</span><span class="special">)</span> <span class="special">}</span> <span class="special">{</span> 298 <span class="special">}</span> 299<span class="special">};</span> 300 301<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">c</span><span class="special">=</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">callcc</span><span class="special">([](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">c</span><span class="special">)</span> <span class="special">{</span> 302 <span class="keyword">for</span> <span class="special">(;;)</span> <span class="special">{</span> 303 <span class="keyword">try</span> <span class="special">{</span> 304 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="string">"entered"</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 305 <span class="identifier">c</span><span class="special">=</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 306 <span class="special">}</span> <span class="keyword">catch</span> <span class="special">(</span><span class="identifier">my_exception</span> <span class="special">&</span> <span class="identifier">ex</span><span class="special">)</span> <span class="special">{</span> 307 <span class="identifier">std</span><span class="special">::</span><span class="identifier">cerr</span> <span class="special"><<</span> <span class="string">"my_exception: "</span> <span class="special"><<</span> <span class="identifier">ex</span><span class="special">.</span><span class="identifier">what</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 308 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">ex</span><span class="special">.</span><span class="identifier">c</span><span class="special">);</span> 309 <span class="special">}</span> 310 <span class="special">}</span> 311 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">c</span><span class="special">);</span> 312<span class="special">});</span> 313<span class="identifier">c</span> <span class="special">=</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">resume_with</span><span class="special">(</span> 314 <span class="special">[](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">c</span><span class="special">){</span> 315 <span class="keyword">throw</span> <span class="identifier">my_exception</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">c</span><span class="special">),</span><span class="string">"abc"</span><span class="special">);</span> 316 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span> <span class="identifier">c</span><span class="special">);</span> 317 <span class="special">});</span> 318 319<span class="identifier">output</span><span class="special">:</span> 320 <span class="identifier">entered</span> 321 <span class="identifier">my_exception</span><span class="special">:</span> <span class="identifier">abc</span> 322</pre> 323<p> 324 In this exception <code class="computeroutput"><span class="identifier">my_exception</span></code> 325 is throw from a function invoked on-top of continuation <code class="computeroutput"><span class="identifier">c</span></code> 326 and catched inside the <code class="computeroutput"><span class="keyword">for</span></code>-loop. 327 </p> 328<h4> 329<a name="context.cc.h6"></a> 330 <span class="phrase"><a name="context.cc.stack_unwinding"></a></span><a class="link" href="cc.html#context.cc.stack_unwinding">Stack 331 unwinding</a> 332 </h4> 333<p> 334 On construction of <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> 335 a stack is allocated. If the <span class="emphasis"><em>context-function</em></span> returns 336 the stack will be destructed. If the <span class="emphasis"><em>context-function</em></span> 337 has not yet returned and the destructor of an valid <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> 338 instance (e.g. <span class="emphasis"><em>continuation::operator bool()</em></span> returns 339 <code class="computeroutput"><span class="keyword">true</span></code>) is called, the stack will 340 be destructed too. 341 </p> 342<div class="important"><table border="0" summary="Important"> 343<tr> 344<td rowspan="2" align="center" valign="top" width="25"><img alt="[Important]" src="../../../../../doc/src/images/important.png"></td> 345<th align="left">Important</th> 346</tr> 347<tr><td align="left" valign="top"><p> 348 Code executed by <span class="emphasis"><em>context-function</em></span> must not prevent the 349 propagation ofs the <span class="emphasis"><em>detail::forced_unwind</em></span> exception. 350 Absorbing that exception will cause stack unwinding to fail. Thus, any code 351 that catches all exceptions must re-throw any pending <span class="emphasis"><em>detail::forced_unwind</em></span> 352 exception. 353 </p></td></tr> 354</table></div> 355<a name="cc_prealloc"></a><h4> 356<a name="context.cc.h7"></a> 357 <span class="phrase"><a name="context.cc.allocating_control_structures_on_top_of_stack"></a></span><a class="link" href="cc.html#context.cc.allocating_control_structures_on_top_of_stack">Allocating 358 control structures on top of stack</a> 359 </h4> 360<p> 361 Allocating control structures on top of the stack requires to allocated the 362 <span class="emphasis"><em>stack_context</em></span> and create the control structure with placement 363 new before <a class="link" href="cc.html#cc"><span class="emphasis"><em>continuation</em></span></a> is created. 364 </p> 365<div class="note"><table border="0" summary="Note"> 366<tr> 367<td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="../../../../../doc/src/images/note.png"></td> 368<th align="left">Note</th> 369</tr> 370<tr><td align="left" valign="top"><p> 371 The user is responsible for destructing the control structure at the top 372 of the stack. 373 </p></td></tr> 374</table></div> 375<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">context</span><span class="special">;</span> 376<span class="comment">// stack-allocator used for (de-)allocating stack</span> 377<span class="identifier">fixedsize_stack</span> <span class="identifier">salloc</span><span class="special">(</span><span class="number">4048</span><span class="special">);</span> 378<span class="comment">// allocate stack space</span> 379<span class="identifier">stack_context</span> <span class="identifier">sctx</span><span class="special">(</span><span class="identifier">salloc</span><span class="special">.</span><span class="identifier">allocate</span><span class="special">());</span> 380<span class="comment">// reserve space for control structure on top of the stack</span> 381<span class="keyword">void</span> <span class="special">*</span> <span class="identifier">sp</span><span class="special">=</span><span class="keyword">static_cast</span><span class="special"><</span><span class="keyword">char</span><span class="special">*>(</span><span class="identifier">sctx</span><span class="special">.</span><span class="identifier">sp</span><span class="special">)-</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">my_control_structure</span><span class="special">);</span> 382<span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span><span class="special">=</span><span class="identifier">sctx</span><span class="special">.</span><span class="identifier">size</span><span class="special">-</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">my_control_structure</span><span class="special">);</span> 383<span class="comment">// placement new creates control structure on reserved space</span> 384<span class="identifier">my_control_structure</span> <span class="special">*</span> <span class="identifier">cs</span><span class="special">=</span><span class="keyword">new</span><span class="special">(</span><span class="identifier">sp</span><span class="special">)</span><span class="identifier">my_control_structure</span><span class="special">(</span><span class="identifier">sp</span><span class="special">,</span><span class="identifier">size</span><span class="special">,</span><span class="identifier">sctx</span><span class="special">,</span><span class="identifier">salloc</span><span class="special">);</span> 385<span class="special">...</span> 386<span class="comment">// destructing the control structure</span> 387<span class="identifier">cs</span><span class="special">->~</span><span class="identifier">my_control_structure</span><span class="special">();</span> 388<span class="special">...</span> 389<span class="keyword">struct</span> <span class="identifier">my_control_structure</span> <span class="special">{</span> 390 <span class="comment">// captured continuation</span> 391 <span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">c</span><span class="special">;</span> 392 393 <span class="keyword">template</span><span class="special"><</span> <span class="keyword">typename</span> <span class="identifier">StackAllocator</span> <span class="special">></span> 394 <span class="identifier">my_control_structure</span><span class="special">(</span><span class="keyword">void</span> <span class="special">*</span> <span class="identifier">sp</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size</span><span class="special">,</span><span class="identifier">stack_context</span> <span class="identifier">sctx</span><span class="special">,</span><span class="identifier">StackAllocator</span> <span class="identifier">salloc</span><span class="special">)</span> <span class="special">:</span> 395 <span class="comment">// create captured continuation</span> 396 <span class="identifier">c</span><span class="special">{}</span> <span class="special">{</span> 397 <span class="identifier">c</span><span class="special">=</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">callcc</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">allocator_arg</span><span class="special">,</span><span class="identifier">preallocated</span><span class="special">(</span><span class="identifier">sp</span><span class="special">,</span><span class="identifier">size</span><span class="special">,</span><span class="identifier">sctx</span><span class="special">),</span><span class="identifier">salloc</span><span class="special">,</span><span class="identifier">entry_func</span><span class="special">);</span> 398 <span class="special">}</span> 399 <span class="special">...</span> 400<span class="special">};</span> 401</pre> 402<h4> 403<a name="context.cc.h8"></a> 404 <span class="phrase"><a name="context.cc.inverting_the_control_flow"></a></span><a class="link" href="cc.html#context.cc.inverting_the_control_flow">Inverting 405 the control flow</a> 406 </h4> 407<pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">ctx</span><span class="special">=</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">context</span><span class="special">;</span> 408<span class="comment">/* 409 * grammar: 410 * P ---> E '\0' 411 * E ---> T {('+'|'-') T} 412 * T ---> S {('*'|'/') S} 413 * S ---> digit | '(' E ')' 414 */</span> 415<span class="keyword">class</span> <span class="identifier">Parser</span><span class="special">{</span> 416 <span class="keyword">char</span> <span class="identifier">next</span><span class="special">;</span> 417 <span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&</span> <span class="identifier">is</span><span class="special">;</span> 418 <span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="keyword">void</span><span class="special">(</span><span class="keyword">char</span><span class="special">)></span> <span class="identifier">cb</span><span class="special">;</span> 419 420 <span class="keyword">char</span> <span class="identifier">pull</span><span class="special">(){</span> 421 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">char_traits</span><span class="special"><</span><span class="keyword">char</span><span class="special">>::</span><span class="identifier">to_char_type</span><span class="special">(</span><span class="identifier">is</span><span class="special">.</span><span class="identifier">get</span><span class="special">());</span> 422 <span class="special">}</span> 423 424 <span class="keyword">void</span> <span class="identifier">scan</span><span class="special">(){</span> 425 <span class="keyword">do</span><span class="special">{</span> 426 <span class="identifier">next</span><span class="special">=</span><span class="identifier">pull</span><span class="special">();</span> 427 <span class="special">}</span> 428 <span class="keyword">while</span><span class="special">(</span><span class="identifier">isspace</span><span class="special">(</span><span class="identifier">next</span><span class="special">));</span> 429 <span class="special">}</span> 430 431<span class="keyword">public</span><span class="special">:</span> 432 <span class="identifier">Parser</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">istream</span><span class="special">&</span> <span class="identifier">is_</span><span class="special">,</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">function</span><span class="special"><</span><span class="keyword">void</span><span class="special">(</span><span class="keyword">char</span><span class="special">)></span> <span class="identifier">cb_</span><span class="special">)</span> <span class="special">:</span> 433 <span class="identifier">next</span><span class="special">(),</span> <span class="identifier">is</span><span class="special">(</span><span class="identifier">is_</span><span class="special">),</span> <span class="identifier">cb</span><span class="special">(</span><span class="identifier">cb_</span><span class="special">)</span> 434 <span class="special">{}</span> 435 436 <span class="keyword">void</span> <span class="identifier">run</span><span class="special">()</span> <span class="special">{</span> 437 <span class="identifier">scan</span><span class="special">();</span> 438 <span class="identifier">E</span><span class="special">();</span> 439 <span class="special">}</span> 440 441<span class="keyword">private</span><span class="special">:</span> 442 <span class="keyword">void</span> <span class="identifier">E</span><span class="special">(){</span> 443 <span class="identifier">T</span><span class="special">();</span> 444 <span class="keyword">while</span> <span class="special">(</span><span class="identifier">next</span><span class="special">==</span><span class="char">'+'</span><span class="special">||</span><span class="identifier">next</span><span class="special">==</span><span class="char">'-'</span><span class="special">){</span> 445 <span class="identifier">cb</span><span class="special">(</span><span class="identifier">next</span><span class="special">);</span> 446 <span class="identifier">scan</span><span class="special">();</span> 447 <span class="identifier">T</span><span class="special">();</span> 448 <span class="special">}</span> 449 <span class="special">}</span> 450 451 <span class="keyword">void</span> <span class="identifier">T</span><span class="special">(){</span> 452 <span class="identifier">S</span><span class="special">();</span> 453 <span class="keyword">while</span> <span class="special">(</span><span class="identifier">next</span><span class="special">==</span><span class="char">'*'</span><span class="special">||</span><span class="identifier">next</span><span class="special">==</span><span class="char">'/'</span><span class="special">){</span> 454 <span class="identifier">cb</span><span class="special">(</span><span class="identifier">next</span><span class="special">);</span> 455 <span class="identifier">scan</span><span class="special">();</span> 456 <span class="identifier">S</span><span class="special">();</span> 457 <span class="special">}</span> 458 <span class="special">}</span> 459 460 <span class="keyword">void</span> <span class="identifier">S</span><span class="special">(){</span> 461 <span class="keyword">if</span> <span class="special">(</span><span class="identifier">isdigit</span><span class="special">(</span><span class="identifier">next</span><span class="special">)){</span> 462 <span class="identifier">cb</span><span class="special">(</span><span class="identifier">next</span><span class="special">);</span> 463 <span class="identifier">scan</span><span class="special">();</span> 464 <span class="special">}</span> 465 <span class="keyword">else</span> <span class="keyword">if</span><span class="special">(</span><span class="identifier">next</span><span class="special">==</span><span class="char">'('</span><span class="special">){</span> 466 <span class="identifier">cb</span><span class="special">(</span><span class="identifier">next</span><span class="special">);</span> 467 <span class="identifier">scan</span><span class="special">();</span> 468 <span class="identifier">E</span><span class="special">();</span> 469 <span class="keyword">if</span> <span class="special">(</span><span class="identifier">next</span><span class="special">==</span><span class="char">')'</span><span class="special">){</span> 470 <span class="identifier">cb</span><span class="special">(</span><span class="identifier">next</span><span class="special">);</span> 471 <span class="identifier">scan</span><span class="special">();</span> 472 <span class="special">}</span><span class="keyword">else</span><span class="special">{</span> 473 <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span><span class="string">"parsing failed"</span><span class="special">);</span> 474 <span class="special">}</span> 475 <span class="special">}</span> 476 <span class="keyword">else</span><span class="special">{</span> 477 <span class="keyword">throw</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">runtime_error</span><span class="special">(</span><span class="string">"parsing failed"</span><span class="special">);</span> 478 <span class="special">}</span> 479 <span class="special">}</span> 480<span class="special">};</span> 481 482<span class="identifier">std</span><span class="special">::</span><span class="identifier">istringstream</span> <span class="identifier">is</span><span class="special">(</span><span class="string">"1+1"</span><span class="special">);</span> 483<span class="comment">// execute parser in new continuation</span> 484<span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="identifier">source</span><span class="special">;</span> 485<span class="comment">// user-code pulls parsed data from parser</span> 486<span class="comment">// invert control flow</span> 487<span class="keyword">char</span> <span class="identifier">c</span><span class="special">;</span> 488<span class="keyword">bool</span> <span class="identifier">done</span><span class="special">=</span><span class="keyword">false</span><span class="special">;</span> 489<span class="identifier">source</span><span class="special">=</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">callcc</span><span class="special">(</span> 490 <span class="special">[&</span><span class="identifier">is</span><span class="special">,&</span><span class="identifier">c</span><span class="special">,&</span><span class="identifier">done</span><span class="special">](</span><span class="identifier">ctx</span><span class="special">::</span><span class="identifier">continuation</span> <span class="special">&&</span> <span class="identifier">sink</span><span class="special">){</span> 491 <span class="comment">// create parser with callback function</span> 492 <span class="identifier">Parser</span> <span class="identifier">p</span><span class="special">(</span><span class="identifier">is</span><span class="special">,</span> 493 <span class="special">[&</span><span class="identifier">sink</span><span class="special">,&</span><span class="identifier">c</span><span class="special">](</span><span class="keyword">char</span> <span class="identifier">c_</span><span class="special">){</span> 494 <span class="comment">// resume main continuation</span> 495 <span class="identifier">c</span><span class="special">=</span><span class="identifier">c_</span><span class="special">;</span> 496 <span class="identifier">sink</span><span class="special">=</span><span class="identifier">sink</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 497 <span class="special">});</span> 498 <span class="comment">// start recursive parsing</span> 499 <span class="identifier">p</span><span class="special">.</span><span class="identifier">run</span><span class="special">();</span> 500 <span class="comment">// signal termination</span> 501 <span class="identifier">done</span><span class="special">=</span><span class="keyword">true</span><span class="special">;</span> 502 <span class="comment">// resume main continuation</span> 503 <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">move</span><span class="special">(</span><span class="identifier">sink</span><span class="special">);</span> 504 <span class="special">});</span> 505<span class="keyword">while</span><span class="special">(!</span><span class="identifier">done</span><span class="special">){</span> 506 <span class="identifier">printf</span><span class="special">(</span><span class="string">"Parsed: %c\n"</span><span class="special">,</span><span class="identifier">c</span><span class="special">);</span> 507 <span class="identifier">source</span><span class="special">=</span><span class="identifier">source</span><span class="special">.</span><span class="identifier">resume</span><span class="special">();</span> 508<span class="special">}</span> 509 510<span class="identifier">output</span><span class="special">:</span> 511 <span class="identifier">Parsed</span><span class="special">:</span> <span class="number">1</span> 512 <span class="identifier">Parsed</span><span class="special">:</span> <span class="special">+</span> 513 <span class="identifier">Parsed</span><span class="special">:</span> <span class="number">1</span> 514</pre> 515<p> 516 In this example a recursive descent parser uses a callback to emit a newly 517 passed symbol. Using <span class="emphasis"><em>call/cc</em></span> the control flow can be inverted, 518 e.g. the user-code pulls parsed symbols from the parser - instead to get pushed 519 from the parser (via callback). 520 </p> 521<p> 522 The data (character) is transferred between the two continuations. 523 </p> 524</div> 525<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 526<td align="left"></td> 527<td align="right"><div class="copyright-footer">Copyright © 2014 Oliver Kowalke<p> 528 Distributed under the Boost Software License, Version 1.0. (See accompanying 529 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>) 530 </p> 531</div></td> 532</tr></table> 533<hr> 534<div class="spirit-nav"> 535<a accesskey="p" href="ff/class__fiber_.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="cc/implementations__fcontext_t__ucontext_t_and_winfiber.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a> 536</div> 537</body> 538</html> 539