Skip to content

Commit

Permalink
Merge pull request sustrik#196 from rokf/typo-fix
Browse files Browse the repository at this point in the history
Tutorial typo fix
  • Loading branch information
sustrik authored Jun 24, 2019
2 parents d958f29 + c9288eb commit de7a917
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
18 changes: 9 additions & 9 deletions website/src/tutorial-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Throughout the tutorial, you will learn how to use coroutines, channels, and soc
## Step 1: Setting up the stage

Start by including the libdill header file. Later we'll need some functionality from the standard library, so include those headers as well:

```c
#include <libdill.h>
#include <assert.h>
Expand Down Expand Up @@ -171,7 +171,7 @@ At this point, the client cannot crash the server, but it can block it. Do the f
3. At yet another terminal, open a new telnet session.
4. Observe that the second session hangs without even asking you for your name.

The reason for this behavior is that the program doesn't even start accepting new connections until the entire dialog with the client has finished. What we want instead is to run any number of dialogues with clients in parallel. And that is where coroutines kick in.
The reason for this behavior is that the program doesn't even start accepting new connections until the entire dialogue with the client has finished. What we want instead is to run any number of dialogues with clients in parallel. And that is where coroutines kick in.

Coroutines are defined using the `coroutine` keyword and launched with the `go()` construct.

Expand All @@ -197,13 +197,13 @@ int main(int argc, char *argv[]) {
assert(s >= 0);
s = suffix_attach(s, "\r\n", 2);
assert(s >= 0);
int cr = go(dialog(s));
int cr = go(dialogue(s));
assert(cr >= 0);
}
}
```
Let's compile it and try the initial experiment once again. As can be seen, one client now cannot block another one. Excellent. Let's move on.
Let's compile it and try the initial experiment once again. As can be seen, one client now cannot block another one. Excellent. Let's move on.
## Step 4: Shutdown
Expand Down Expand Up @@ -244,7 +244,7 @@ int main(int argc, char *argv[]) {
rc = hclose(ls);
assert(rc == 0);
return 0;
return 0;
}
```

Expand All @@ -258,7 +258,7 @@ Now try to compile this step and run it under valgrind. (Don't forget to compile
==179895== HEAP SUMMARY:
==179895== in use at exit: 0 bytes in 0 blocks
==179895== total heap usage: 11 allocs, 11 frees, 1,329,272 bytes allocated
==179895==
==179895==
==179895== All heap blocks were freed -- no leaks are possible
```

Expand All @@ -270,7 +270,7 @@ File descriptors can be a scarce resource. If a client connects to the greetserv

To deal with the problem, we are going to timeout the whole client/server dialogue. If it takes more than *10* seconds, the server will kill the connection at once.

One thing to note is that libdill uses deadlines rather than the more conventional timeouts. In other words, you specify the time instant by which you want the operation to finish rather than the maximum time it should take to run it. To construct deadlines easily, libdill provides the `now()` function. The deadline is expressed in milliseconds, which means you can create a deadline one minure in the future as follows:
One thing to note is that libdill uses deadlines rather than the more conventional timeouts. In other words, you specify the time instant by which you want the operation to finish rather than the maximum time it should take to run it. To construct deadlines easily, libdill provides the `now()` function. The deadline is expressed in milliseconds, which means you can create a deadline one minute in the future as follows:

```c
int64_t deadline = now() + 60000;
Expand All @@ -296,7 +296,7 @@ This can be achieved by calling `bundle_wait()` on the `dialogue()` coroutine bu
```c
rc = bundle_wait(b, now() + 10000);
assert(rc == 0 || (rc < 0 && errno == ETIMEDOUT));
```
```
## Step 6: Communication among coroutines
Expand Down Expand Up @@ -356,7 +356,7 @@ coroutine void statistics(int ch) {
int active = 0;
int succeeded = 0;
int failed = 0;
while(1) {
int op;
int rc = chrecv(ch, &op, sizeof(op), -1);
Expand Down
12 changes: 6 additions & 6 deletions website/tutorial-basics.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ <h2 id="step-3-making-it-parallel">Step 3: Making it parallel</h2>
<li>At yet another terminal, open a new telnet session.</li>
<li>Observe that the second session hangs without even asking you for your name.</li>
</ol>
<p>The reason for this behavior is that the program doesn't even start accepting new connections until the entire dialog with the client has finished. What we want instead is to run any number of dialogues with clients in parallel. And that is where coroutines kick in.</p>
<p>The reason for this behavior is that the program doesn't even start accepting new connections until the entire dialogue with the client has finished. What we want instead is to run any number of dialogues with clients in parallel. And that is where coroutines kick in.</p>
<p>Coroutines are defined using the <code>coroutine</code> keyword and launched with the <code>go()</code> construct.</p>
<p>In our case, we can move the code performing the dialogue with the client into a separate function and launch it as a coroutine:</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c">coroutine <span class="dt">void</span> dialogue(<span class="dt">int</span> s) {
Expand All @@ -135,7 +135,7 @@ <h2 id="step-3-making-it-parallel">Step 3: Making it parallel</h2>
assert(s &gt;= <span class="dv">0</span>);
s = suffix_attach(s, <span class="st">&quot;</span><span class="sc">\r\n</span><span class="st">&quot;</span>, <span class="dv">2</span>);
assert(s &gt;= <span class="dv">0</span>);
<span class="dt">int</span> cr = go(dialog(s));
<span class="dt">int</span> cr = go(dialogue(s));
assert(cr &gt;= <span class="dv">0</span>);
}
}</code></pre></div>
Expand Down Expand Up @@ -170,21 +170,21 @@ <h2 id="step-4-shutdown">Step 4: Shutdown</h2>
rc = hclose(ls);
assert(rc == <span class="dv">0</span>);

<span class="cf">return</span> <span class="dv">0</span>;
<span class="cf">return</span> <span class="dv">0</span>;
}</code></pre></div>
<p>One thing to remember about canceling coroutines is that once a coroutine is canceled all the blocking operations within the coroutine, such as reading from a socket or sleeping, will start returning <code>ECANCELED</code> error. The coroutine should then deallocate all its resources and exit.</p>
<p>Looking at our <code>dialogue</code> coroutine it turns out that it already does that. It responds to any error, including <code>ECANCELED</code> by closing the socket handle and exiting.</p>
<p>Now try to compile this step and run it under valgrind. (Don't forget to compile libdill itself with <code>--enable-valgrind</code> and <code>--disable-shared</code> options!) Here's what you'll get:</p>
<pre><code>==179895== HEAP SUMMARY:
==179895== in use at exit: 0 bytes in 0 blocks
==179895== total heap usage: 11 allocs, 11 frees, 1,329,272 bytes allocated
==179895==
==179895==
==179895== All heap blocks were freed -- no leaks are possible</code></pre>
<p>To get some background on how object lifetimes are supposed to be managed in libdill read the article about <a href="structured-concurrency.html">structured concurrency</a>.</p>
<h2 id="step-5-deadlines">Step 5: Deadlines</h2>
<p>File descriptors can be a scarce resource. If a client connects to the greetserver and lets the dialogue hang without entering a name, one file descriptor on the server side is, for all intents and purposes, wasted.</p>
<p>To deal with the problem, we are going to timeout the whole client/server dialogue. If it takes more than <em>10</em> seconds, the server will kill the connection at once.</p>
<p>One thing to note is that libdill uses deadlines rather than the more conventional timeouts. In other words, you specify the time instant by which you want the operation to finish rather than the maximum time it should take to run it. To construct deadlines easily, libdill provides the <code>now()</code> function. The deadline is expressed in milliseconds, which means you can create a deadline one minure in the future as follows:</p>
<p>One thing to note is that libdill uses deadlines rather than the more conventional timeouts. In other words, you specify the time instant by which you want the operation to finish rather than the maximum time it should take to run it. To construct deadlines easily, libdill provides the <code>now()</code> function. The deadline is expressed in milliseconds, which means you can create a deadline one minute in the future as follows:</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="dt">int64_t</span> deadline = now() + <span class="dv">60000</span>;</code></pre></div>
<p>Furthermore, you have to modify all potentially blocking function calls in the program to take the deadline parameter. In our case:</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="dt">int64_t</span> deadline = now() + <span class="dv">60000</span>;
Expand Down Expand Up @@ -237,7 +237,7 @@ <h2 id="step-6-communication-among-coroutines">Step 6: Communication among corou
<span class="dt">int</span> active = <span class="dv">0</span>;
<span class="dt">int</span> succeeded = <span class="dv">0</span>;
<span class="dt">int</span> failed = <span class="dv">0</span>;

<span class="cf">while</span>(<span class="dv">1</span>) {
<span class="dt">int</span> op;
<span class="dt">int</span> rc = chrecv(ch, &amp;op, <span class="kw">sizeof</span>(op), <span class="dv">-1</span>);
Expand Down

0 comments on commit de7a917

Please sign in to comment.