Files
tantivy/chan/index.html
2018-02-12 02:52:50 +00:00

544 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `chan` crate.">
<meta name="keywords" content="rust, rustlang, rust-lang, chan">
<title>chan - Rust</title>
<link rel="stylesheet" type="text/css" href="../normalize.css">
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
<link rel="stylesheet" type="text/css" href="../dark.css">
<link rel="stylesheet" type="text/css" href="../main.css" id="themeStyle">
<script src="../storage.js"></script>
</head>
<body class="rustdoc mod">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<nav class="sidebar">
<div class="sidebar-menu">&#9776;</div>
<p class='location'>Crate chan</p><div class="sidebar-elems"><div class="block items"><ul><li><a href="#macros">Macros</a></li><li><a href="#structs">Structs</a></li><li><a href="#functions">Functions</a></li></ul></div><p class='location'></p><script>window.sidebarCurrent = {name: 'chan', ty: 'mod', relpath: '../'};</script></div>
</nav>
<div class="theme-picker">
<button id="theme-picker" aria-label="Pick another theme!">
<img src="../brush.svg" width="18" alt="Pick another theme!">
</button>
<div id="theme-choices"></div>
</div>
<script src="../theme.js"></script>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press S to search, ? for more options…"
type="search">
</div>
</form>
</nav>
<section id='main' class="content">
<h1 class='fqn'><span class='in-band'>Crate <a class="mod" href=''>chan</a></span><span class='out-of-band'><span id='render-detail'>
<a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
[<span class='inner'>&#x2212;</span>]
</a>
</span><a class='srclink' href='../src/chan/lib.rs.html#1-1760' title='goto source code'>[src]</a></span></h1>
<div class='docblock'><p>This crate provides an implementation of a multi-producer, multi-consumer
channel. Channels come in three varieties:</p>
<ol>
<li>Asynchronous channels. Sends never block. Its buffer is only limited by the
available resources on the system.</li>
<li>Synchronous buffered channels. Sends block when the buffer is full. The
buffer is depleted by receiving on the channel.</li>
<li>Rendezvous channels (synchronous channels without a buffer). Sends block
until a receive has consumed the value sent. When a sender and receiver
synchronize, they are said to <em>rendezvous</em>.</li>
</ol>
<p>Asynchronous channels are created with <code>chan::async()</code>. Synchronous channels
are created with <code>chan::sync(k)</code> where <code>k</code> is the buffer size. Rendezvous
channels are created with <code>chan::sync(0)</code>.</p>
<p>All channels are split into the same two types upon creation: a <code>Sender</code> and
a <code>Receiver</code>. Additional senders and receivers can be created with reckless
abandon by calling <code>clone</code>.</p>
<p>When all senders are dropped, the channel is closed and no other sends are
possible. In a channel with a buffer, receivers continue to consume values
until the buffer is empty, at which point, a <code>None</code> value is always returned
immediately.</p>
<p>No special semantics are enforced when all receivers are dropped. Asynchronous
sends will continue to work. Synchronous sends will block indefinitely when
the buffer is full. A send on a rendezvous channel will also block
indefinitely. (<strong>NOTE</strong>: This could be changed!)</p>
<p>All channels satisfy <em>both</em> <code>Send</code> and <code>Sync</code> and can be freely mixed in
<code>chan_select!</code>. Said differently, the synchronization semantics of a channel
are encoded upon construction, but are otherwise indistinguishable to the
type system.</p>
<p>Values sent on channels are subject to the normal restrictions Rust has on
values crossing thread boundaries. i.e., Values must implement <code>Send</code> and/or
<code>Sync</code>. (An <code>Rc&lt;T&gt;</code> <em>cannot</em> be sent on a channel, but a channel can be sent
on a channel!)</p>
<h1 id="example-rendezvous-channel" class="section-header"><a href="#example-rendezvous-channel">Example: rendezvous channel</a></h1>
<p>A simple example demonstrating a rendezvous channel:</p>
<pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">thread</span>;
<span class="kw">let</span> (<span class="ident">send</span>, <span class="ident">recv</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> <span class="ident">send</span>.<span class="ident">send</span>(<span class="number">5</span>));
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">recv</span>.<span class="ident">recv</span>(), <span class="prelude-val">Some</span>(<span class="number">5</span>)); <span class="comment">// blocks until the previous send occurs</span></pre>
<h1 id="example-synchronous-channel" class="section-header"><a href="#example-synchronous-channel">Example: synchronous channel</a></h1>
<p>Similarly, an example demonstrating a synchronous channel:</p>
<pre class="rust rust-example-rendered">
<span class="kw">let</span> (<span class="ident">send</span>, <span class="ident">recv</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">1</span>);
<span class="ident">send</span>.<span class="ident">send</span>(<span class="number">5</span>); <span class="comment">// doesn&#39;t block because of the buffer</span>
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">recv</span>.<span class="ident">recv</span>(), <span class="prelude-val">Some</span>(<span class="number">5</span>));</pre>
<h1 id="example-multiple-producers-and-multiple-consumers" class="section-header"><a href="#example-multiple-producers-and-multiple-consumers">Example: multiple producers and multiple consumers</a></h1>
<p>An example demonstrating multiple consumers and multiple producers:</p>
<pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">thread</span>;
<span class="kw">let</span> <span class="ident">r</span> <span class="op">=</span> {
<span class="kw">let</span> (<span class="ident">s</span>, <span class="ident">r</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="kw">for</span> <span class="ident">letter</span> <span class="kw">in</span> <span class="macro">vec</span><span class="macro">!</span>[<span class="string">&#39;a&#39;</span>, <span class="string">&#39;b&#39;</span>, <span class="string">&#39;c&#39;</span>, <span class="string">&#39;d&#39;</span>] {
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">s</span>.<span class="ident">clone</span>();
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> {
<span class="kw">for</span> _ <span class="kw">in</span> <span class="number">0</span>..<span class="number">10</span> {
<span class="ident">s</span>.<span class="ident">send</span>(<span class="ident">letter</span>);
}
});
}
<span class="comment">// This extra lexical scope will drop the initial</span>
<span class="comment">// sender we created. Thus, the channel will be</span>
<span class="comment">// closed when all threads spawned above has completed.</span>
<span class="ident">r</span>
};
<span class="comment">// A wait group lets us synchronize the completion of multiple threads.</span>
<span class="kw">let</span> <span class="ident">wg</span> <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">WaitGroup</span>::<span class="ident">new</span>();
<span class="kw">for</span> _ <span class="kw">in</span> <span class="number">0</span>..<span class="number">4</span> {
<span class="ident">wg</span>.<span class="ident">add</span>(<span class="number">1</span>);
<span class="kw">let</span> <span class="ident">wg</span> <span class="op">=</span> <span class="ident">wg</span>.<span class="ident">clone</span>();
<span class="kw">let</span> <span class="ident">r</span> <span class="op">=</span> <span class="ident">r</span>.<span class="ident">clone</span>();
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> {
<span class="kw">for</span> <span class="ident">letter</span> <span class="kw">in</span> <span class="ident">r</span> {
<span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;Received letter: {}&quot;</span>, <span class="ident">letter</span>);
}
<span class="ident">wg</span>.<span class="ident">done</span>();
});
}
<span class="comment">// If this was the end of the process and we didn&#39;t call `wg.wait()`, then</span>
<span class="comment">// the process might quit before all of the consumers were done.</span>
<span class="comment">// `wg.wait()` will block until all `wg.done()` calls have finished.</span>
<span class="ident">wg</span>.<span class="ident">wait</span>();</pre>
<h1 id="example-select-on-multiple-channel-sendsreceives" class="section-header"><a href="#example-select-on-multiple-channel-sendsreceives">Example: Select on multiple channel sends/receives</a></h1>
<p>An example showing how to use <code>chan_select!</code> to synchronize on sends
or receives.</p>
<pre class="rust rust-example-rendered">
<span class="attribute">#[<span class="ident">macro_use</span>]</span>
<span class="kw">extern</span> <span class="kw">crate</span> <span class="ident">chan</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">thread</span>;
<span class="comment">// Emits the fibonacci sequence on the given channel until `quit` receives</span>
<span class="comment">// a sentinel value.</span>
<span class="kw">fn</span> <span class="ident">fibonacci</span>(<span class="ident">s</span>: <span class="ident">chan</span>::<span class="ident">Sender</span><span class="op">&lt;</span><span class="ident">u64</span><span class="op">&gt;</span>, <span class="ident">quit</span>: <span class="ident">chan</span>::<span class="ident">Receiver</span><span class="op">&lt;</span>()<span class="op">&gt;</span>) {
<span class="kw">let</span> (<span class="kw-2">mut</span> <span class="ident">x</span>, <span class="kw-2">mut</span> <span class="ident">y</span>) <span class="op">=</span> (<span class="number">0</span>, <span class="number">1</span>);
<span class="kw">loop</span> {
<span class="comment">// Select will block until at least one of `s.send` or `quit.recv`</span>
<span class="comment">// is ready to succeed. At which point, it will choose exactly one</span>
<span class="comment">// send/receive to synchronize.</span>
<span class="macro">chan_select</span><span class="macro">!</span> {
<span class="ident">s</span>.<span class="ident">send</span>(<span class="ident">x</span>) <span class="op">=&gt;</span> {
<span class="kw">let</span> <span class="ident">oldx</span> <span class="op">=</span> <span class="ident">x</span>;
<span class="ident">x</span> <span class="op">=</span> <span class="ident">y</span>;
<span class="ident">y</span> <span class="op">=</span> <span class="ident">oldx</span> <span class="op">+</span> <span class="ident">y</span>;
},
<span class="ident">quit</span>.<span class="ident">recv</span>() <span class="op">=&gt;</span> {
<span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;quit&quot;</span>);
<span class="kw">return</span>;
}
}
}
}
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="kw">let</span> (<span class="ident">s</span>, <span class="ident">r</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="kw">let</span> (<span class="ident">qs</span>, <span class="ident">qr</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="comment">// Spawn a thread and ask for the first 10 numbers in the fibonacci</span>
<span class="comment">// sequence.</span>
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> {
<span class="kw">for</span> _ <span class="kw">in</span> <span class="number">0</span>..<span class="number">10</span> {
<span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">r</span>.<span class="ident">recv</span>().<span class="ident">unwrap</span>());
}
<span class="comment">// Dropping all sending channels causes the receive channel to</span>
<span class="comment">// immediately and always synchronize (because the channel is closed).</span>
<span class="ident">drop</span>(<span class="ident">qs</span>);
});
<span class="ident">fibonacci</span>(<span class="ident">s</span>, <span class="ident">qr</span>);
}</pre>
<h1 id="example-non-blocking-sendsreceives" class="section-header"><a href="#example-non-blocking-sendsreceives">Example: non-blocking sends/receives</a></h1>
<p>This crate specifically does not expose methods like <code>try_send</code> or <code>try_recv</code>.
Instead, you should prefer using <code>chan_select!</code> to perform a non-blocking
send or receive. This can be done by telling select what to do when no
synchronization events are available.</p>
<pre class="rust rust-example-rendered">
<span class="kw">let</span> (<span class="ident">s</span>, _) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="macro">chan_select</span><span class="macro">!</span> {
<span class="ident">default</span> <span class="op">=&gt;</span> <span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;Send failed.&quot;</span>),
<span class="ident">s</span>.<span class="ident">send</span>(<span class="string">&quot;some data&quot;</span>) <span class="op">=&gt;</span> <span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;Send succeeded.&quot;</span>),
}</pre>
<p>When <code>chan_select!</code> first runs, it will check if <code>s.send(...)</code> can succeed
<em>without blocking</em>. If so, <code>chan_select!</code> will permit the channels to
rendezvous. However, if there is no <code>recv</code> call to accept the send, then
<code>chan_select!</code> will immediately execute the <code>default</code> arm.</p>
<h1 id="example-the-sentinel-channel-idiom" class="section-header"><a href="#example-the-sentinel-channel-idiom">Example: the sentinel channel idiom</a></h1>
<p>When writing concurrent programs with <code>chan</code>, you will often find that you need
to somehow &quot;wait&quot; until some operation is done. For example, let's say you want
to run a function in a separate thread, but wait until it completes. Here's
one way to do it:</p>
<pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">thread</span>;
<span class="kw">fn</span> <span class="ident">do_work</span>(<span class="ident">done</span>: <span class="ident">chan</span>::<span class="ident">Sender</span><span class="op">&lt;</span>()<span class="op">&gt;</span>) {
<span class="comment">// do something</span>
<span class="comment">// signal that we&#39;re done.</span>
<span class="ident">done</span>.<span class="ident">send</span>(());
}
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="kw">let</span> (<span class="ident">sdone</span>, <span class="ident">rdone</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> <span class="ident">do_work</span>(<span class="ident">sdone</span>));
<span class="comment">// block until work is done, and then quit the program.</span>
<span class="ident">rdone</span>.<span class="ident">recv</span>();
}</pre>
<p>In effect, we've created a new channel that sends unit values. When we're
done doing work, we send a unit value and <code>main</code> waits for it to be delivered.</p>
<p>Another way of achieving the same thing is to simply close the channel. Once
the channel is closed, any previously blocked receive operations become
immediately unblocked. What's even cooler is that channels are closed
automatically when all senders are dropped. So the new program looks something
like this:</p>
<pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">thread</span>;
<span class="kw">fn</span> <span class="ident">do_work</span>(<span class="ident">_done</span>: <span class="ident">chan</span>::<span class="ident">Sender</span><span class="op">&lt;</span>()<span class="op">&gt;</span>) {
<span class="comment">// do something</span>
}
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="kw">let</span> (<span class="ident">sdone</span>, <span class="ident">rdone</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> <span class="ident">do_work</span>(<span class="ident">sdone</span>));
<span class="comment">// block until work is done, and then quit the program.</span>
<span class="ident">rdone</span>.<span class="ident">recv</span>();
}</pre>
<p>We no longer need to explicitly do anything with the <code>_done</code> channel. We give
<code>do_work</code> ownership of the channel, but as soon as the function stops
executing, <code>_done</code> is dropped, the channel is closed and <code>rdone.recv()</code>
unblocks.</p>
<h1 id="example-i-want-more" class="section-header"><a href="#example-i-want-more">Example: I want more!</a></h1>
<p>There are some examples in this crate's repository:
https://github.com/BurntSushi/chan/tree/master/examples</p>
<p>Here is a nice example using the <code>chan-signal</code> crate to read lines from
stdin while gracefully quitting after receiving a <code>INT</code> or <code>TERM</code>
signal:
https://github.com/BurntSushi/chan-signal/blob/master/examples/read_names.rs</p>
<p>A non-trivial program for periodically sending email with the output of
running a command: https://github.com/BurntSushi/rust-cmail (The source is
commented more heavily than normal.)</p>
<h1 id="when-are-channel-operations-non-blocking" class="section-header"><a href="#when-are-channel-operations-non-blocking">When are channel operations non-blocking?</a></h1>
<p>Non-blocking in this context means &quot;a send/recv operation can synchronize
immediately.&quot; (Under the hood, a mutex may still be acquired, which could
block.)</p>
<p>The following is a list of all cases where a channel operation is considered
non-blocking:</p>
<ul>
<li>A send on a synchronous channel whose buffer is not full.</li>
<li>A receive on a synchronous channel with a non-empty buffer.</li>
<li>A send on an asynchronous channel.</li>
<li>A rendezvous send or recv when a corresponding recv or send operation is
already blocked, respectively.</li>
<li>A receive on any closed channel.</li>
</ul>
<p>Non-blocking semantics are important because they affect the behavior of
<code>chan_select!</code>. In particular, a <code>chan_select!</code> with a <code>default</code> arm will
execute the <code>default</code> case if and only if all other operations are blocked.</p>
<h1 id="which-channel-type-should-i-use" class="section-header"><a href="#which-channel-type-should-i-use">Which channel type should I use?</a></h1>
<p><a href="http://www.eros-os.org/pipermail/e-lang/2003-January/008183.html">From Ken Kahn</a>:</p>
<blockquote>
<p>About 25 years ago I went to dinner with Carl Hewitt and Robin Milner (of
CSS and pi calculus fame) and they were arguing about synchronous vs.
asynchronous communication primitives. Carl used the post office metaphor
while Robin used the telephone. Both quickly admitted that one can implement
one in the other.</p>
</blockquote>
<p>With three channel types to choose from, it may not always be clear which one
you should use. In fact, there has been a long debate over which are better.
Here are some rough guidelines:</p>
<ul>
<li>Historically, asynchronous channels have been associated with the actor
model, which means they're a little out of place in a library inspired by
communicating sequential processes. Nevertheless, an unconstrained buffer can
be occasionally useful.</li>
<li>Synchronous channels are useful because their stricter synchronization
semantics can make it easier to reason about the flow of your program. In
particular, with a rendezvous channel, one knows that a <code>send</code> unblocks only
when a corresponding <code>recv</code> consumes the sent value. This makes it <em>feel</em>
an awful lot like a function call!</li>
</ul>
<h1 id="warning-leaks" class="section-header"><a href="#warning-leaks">Warning: leaks</a></h1>
<p>Channels can be leaked! In particular, if all receivers have been dropped,
then any future sends will block. Usually this is indicative of a bug in your
program.</p>
<p>For example, consider a &quot;generator&quot; style pattern where a thread produces
values on a channel and another thread consumes in an iterator.</p>
<pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">thread</span>;
<span class="kw">let</span> (<span class="ident">s</span>, <span class="ident">r</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>(<span class="number">0</span>);
<span class="ident">thread</span>::<span class="ident">spawn</span>(<span class="kw">move</span> <span class="op">||</span> {
<span class="kw">for</span> <span class="ident">val</span> <span class="kw">in</span> <span class="ident">r</span> {
<span class="kw">if</span> <span class="ident">val</span> <span class="op">&gt;=</span> <span class="number">2</span> {
<span class="kw">break</span>;
}
}
});
<span class="ident">s</span>.<span class="ident">send</span>(<span class="number">1</span>);
<span class="ident">s</span>.<span class="ident">send</span>(<span class="number">2</span>);
<span class="comment">// This will deadlock because the loop in the thread</span>
<span class="comment">// above quits after receiving `2`.</span>
<span class="ident">s</span>.<span class="ident">send</span>(<span class="number">3</span>);</pre>
<p>If the iterator loop quits early, the channel's buffer could fill up, which
will indefinitely block all future send operations.</p>
<p>(These leaks/deadlocks are detectable in most circumstances, and a <code>send</code>
operation could be made to wake up and either return an error or panic. The
semantics here are still experimental.)</p>
<h1 id="warning-more-leaks" class="section-header"><a href="#warning-more-leaks">Warning: more leaks</a></h1>
<p>It will always be possible to leak a channel in safe code regardless of the
channel's semantics. For example:</p>
<pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">mem</span>::<span class="ident">forget</span>;
<span class="kw">let</span> (<span class="ident">s</span>, <span class="ident">r</span>) <span class="op">=</span> <span class="ident">chan</span>::<span class="ident">sync</span>::<span class="op">&lt;</span>()<span class="op">&gt;</span>(<span class="number">0</span>);
<span class="ident">forget</span>(<span class="ident">s</span>);
<span class="comment">// Blocks forever because the channel is never closed.</span>
<span class="ident">r</span>.<span class="ident">recv</span>();</pre>
<p>In this case, it is impossible for the channel to close because the internal
reference count will never reach <code>0</code>.</p>
<h1 id="warning-performance" class="section-header"><a href="#warning-performance">Warning: performance</a></h1>
<p>The primary purpose of this crate is to provide a safe, concurrent abstraction.
Notably, it is <em>not</em> a zero-cost abstraction. It is not even a near-zero-cost
abstraction. Throughput on a channel is startlingly low (see the benchmarks
in this crate's repository). Therefore, the channels provided in this crate
are most useful as a means to structure concurrent programs at a coarse level.</p>
<p>If your requirements call for performant synchronization of data, <code>chan</code> is not
the crate you're looking for.</p>
<h1 id="prior-art" class="section-header"><a href="#prior-art">Prior art</a></h1>
<p>The semantics encoded in the channels provided by this crate should mirror or
closely mirror the semantics provided by channels in Go. This includes
select statements! The major difference between concurrent programs written
with <code>chan</code> and concurrent programs written with Go is that Go programs can
benefit from being fast and loose with creating goroutines. In <code>chan</code>, each
&quot;goroutine&quot; is just an OS thread.</p>
<p>In terms of writing code:</p>
<ol>
<li>Go programs will feature explicit closing of channels. In <code>chan</code>, channels
are closed <strong>only</strong> when all senders have been dropped.</li>
<li>Since there is no such thing as a &quot;nil&quot; channel in <code>chan</code>, the semantics Go
has for nil channels (both sends and receives block indefinitely) do not
exist in <code>chan</code>.</li>
<li><code>chan</code> does not expose <code>len</code> or <code>cap</code> methods. (For no reason other than
to start with a totally minimal API. In particular, calling <code>len</code> or <code>cap</code>
on a channel is often The Wrong Thing. But not always. So this restriction
may be lifted in the future.)</li>
<li>In <code>chan</code>, all channels are either senders or receivers. There is no
&quot;bidirectional&quot; channel. This is manifest in how channel memory is managed:
channels are closed when all senders are dropped.</li>
</ol>
<p>Of course, Go is not the origin of these ideas, but it has been the
strongest influence on the design of this library, and at least one of its
authors has done substantial research on the integration of CSP and programming
languages.</p>
</div><h2 id='macros' class='section-header'><a href="#macros">Macros</a></h2>
<table>
<tr class=' module-item'>
<td><a class="macro" href="macro.chan_select.html"
title='macro chan::chan_select'>chan_select</a></td>
<td class='docblock-short'>
<p>Synchronize on at most one channel send or receive operation.</p>
</td>
</tr></table><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
<table>
<tr class=' module-item'>
<td><a class="struct" href="struct.Iter.html"
title='struct chan::Iter'>Iter</a></td>
<td class='docblock-short'>
<p>An iterator over values received in a channel.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="struct" href="struct.Receiver.html"
title='struct chan::Receiver'>Receiver</a></td>
<td class='docblock-short'>
<p>The receiving half of a channel.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="struct" href="struct.Sender.html"
title='struct chan::Sender'>Sender</a></td>
<td class='docblock-short'>
<p>The sending half of a channel.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="struct" href="struct.WaitGroup.html"
title='struct chan::WaitGroup'>WaitGroup</a></td>
<td class='docblock-short'>
<p><code>WaitGroup</code> provides synchronization on the completion of threads.</p>
</td>
</tr></table><h2 id='functions' class='section-header'><a href="#functions">Functions</a></h2>
<table>
<tr class=' module-item'>
<td><a class="fn" href="fn.after.html"
title='fn chan::after'>after</a></td>
<td class='docblock-short'>
<p>Creates a new rendezvous channel that is dropped after a timeout.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="fn" href="fn.after_ms.html"
title='fn chan::after_ms'>after_ms</a></td>
<td class='docblock-short'>
<p>Creates a new rendezvous channel that is dropped after a timeout.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="fn" href="fn.async.html"
title='fn chan::async'>async</a></td>
<td class='docblock-short'>
<p>Create an asynchronous channel with an unbounded buffer.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="fn" href="fn.sync.html"
title='fn chan::sync'>sync</a></td>
<td class='docblock-short'>
<p>Create a synchronous channel with a possibly empty buffer.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="fn" href="fn.tick.html"
title='fn chan::tick'>tick</a></td>
<td class='docblock-short'>
<p>Creates a new rendezvous channel that is &quot;ticked&quot; every duration.</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="fn" href="fn.tick_ms.html"
title='fn chan::tick_ms'>tick_ms</a></td>
<td class='docblock-short'>
<p>Creates a new rendezvous channel that is &quot;ticked&quot; every duration.</p>
</td>
</tr></table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<aside id="help" class="hidden">
<div>
<h1 class="hidden">Help</h1>
<div class="shortcuts">
<h2>Keyboard Shortcuts</h2>
<dl>
<dt><kbd>?</kbd></dt>
<dd>Show this help dialog</dd>
<dt><kbd>S</kbd></dt>
<dd>Focus the search field</dd>
<dt><kbd></kbd></dt>
<dd>Move up in search results</dd>
<dt><kbd></kbd></dt>
<dd>Move down in search results</dd>
<dt><kbd></kbd></dt>
<dd>Switch tab</dd>
<dt><kbd>&#9166;</kbd></dt>
<dd>Go to active search result</dd>
<dt><kbd>+</kbd></dt>
<dd>Expand all sections</dd>
<dt><kbd>-</kbd></dt>
<dd>Collapse all sections</dd>
</dl>
</div>
<div class="infos">
<h2>Search Tricks</h2>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>type</code>, <code>macro</code>,
and <code>const</code>.
</p>
<p>
Search functions by type signature (e.g.
<code>vec -> usize</code> or <code>* -> vec</code>)
</p>
</div>
</div>
</aside>
<script>
window.rootPath = "../";
window.currentCrate = "chan";
</script>
<script src="../main.js"></script>
<script defer src="../search-index.js"></script>
</body>
</html>