blob: d8572be29185774d266bf670ccadb7aa80580c1f [file] [log] [blame]
<!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="Oneshot spsc (single producer, single consumer) channel. Meaning each channel instance can only transport a single message. This has a few nice outcomes. One thing is that the implementation can be very efficient, utilizing the knowledge that there will only be one message. But more importantly, it allows the API to be expressed in such a way that certain edge cases that you don’t want to care about when only sending a single message on a channel does not exist. For example: The sender can’t be copied or cloned, and the send method takes ownership and consumes the sender. So you are guaranteed, at the type level, that there can only be one message sent."><meta name="keywords" content="rust, rustlang, rust-lang, oneshot"><title>oneshot - Rust</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../SourceCodePro-Semibold.ttf.woff2"><link rel="stylesheet" href="../normalize.css"><link rel="stylesheet" href="../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" href="../ayu.css" disabled><link rel="stylesheet" href="../dark.css" disabled><link rel="stylesheet" href="../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../storage.js"></script><script defer src="../crates.js"></script><script defer src="../main.js"></script><noscript><link rel="stylesheet" href="../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../favicon.svg"></head><body class="rustdoc mod crate"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="sidebar-logo" href="../oneshot/index.html"><div class="logo-container"><img class="rust-logo" src="../rust-logo.svg" alt="logo"></div></a><h2></h2></nav><nav class="sidebar"><a class="sidebar-logo" href="../oneshot/index.html"><div class="logo-container"><img class="rust-logo" src="../rust-logo.svg" alt="logo"></div></a><h2 class="location"><a href="#">Crate oneshot</a></h2><div class="sidebar-elems"><ul class="block"><li class="version">Version 0.1.5</li><li><a id="all-types" href="all.html">All Items</a></li></ul><section><ul class="block"><li><a href="#structs">Structs</a></li><li><a href="#enums">Enums</a></li><li><a href="#functions">Functions</a></li></ul></section></div></nav><main><div class="width-limiter"><nav class="sub"><form class="search-form"><div class="search-container"><span></span><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press ‘S’ to search, ‘?’ for more options…" type="search"><div id="help-button" title="help" tabindex="-1"><a href="../help.html">?</a></div><div id="settings-menu" tabindex="-1"><a href="../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../wheel.svg"></a></div></div></form></nav><section id="main-content" class="content"><div class="main-heading"><h1 class="fqn">Crate <a class="mod" href="#">oneshot</a><button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"><img src="../clipboard.svg" width="19" height="18" alt="Copy item path"></button></h1><span class="out-of-band"><a class="srclink" href="../src/oneshot/lib.rs.html#1-1193">source</a> · <a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">[<span class="inner">&#x2212;</span>]</a></span></div><details class="rustdoc-toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Oneshot spsc (single producer, single consumer) channel. Meaning each channel instance
can only transport a single message. This has a few nice outcomes. One thing is that
the implementation can be very efficient, utilizing the knowledge that there will
only be one message. But more importantly, it allows the API to be expressed in such
a way that certain edge cases that you don’t want to care about when only sending a
single message on a channel does not exist. For example: The sender can’t be copied
or cloned, and the send method takes ownership and consumes the sender.
So you are guaranteed, at the type level, that there can only be one message sent.</p>
<p>The sender’s send method is non-blocking, and potentially lock- and wait-free.
See documentation on <a href="struct.Sender.html#method.send" title="Sender::send">Sender::send</a> for situations where it might not be fully wait-free.
The receiver supports both lock- and wait-free <code>try_recv</code> as well as indefinite and time
limited thread blocking receive operations. The receiver also implements <code>Future</code> and
supports asynchronously awaiting the message.</p>
<h2 id="examples"><a href="#examples">Examples</a></h2>
<p>This example sets up a background worker that processes requests coming in on a standard
mpsc channel and replies on a oneshot channel provided with each request. The worker can
be interacted with both from sync and async contexts since the oneshot receiver
can receive both blocking and async.</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::sync::mpsc;
<span class="kw">use </span>std::thread;
<span class="kw">use </span>std::time::Duration;
<span class="kw">type </span>Request = String;
<span class="comment">// Starts a background thread performing some computation on requests sent to it.
// Delivers the response back over a oneshot channel.
</span><span class="kw">fn </span>spawn_processing_thread() -&gt; mpsc::Sender&lt;(Request, oneshot::Sender&lt;usize&gt;)&gt; {
<span class="kw">let </span>(request_sender, request_receiver) = mpsc::channel::&lt;(Request, oneshot::Sender&lt;usize&gt;)&gt;();
thread::spawn(<span class="kw">move </span>|| {
<span class="kw">for </span>(request_data, response_sender) <span class="kw">in </span>request_receiver.iter() {
<span class="kw">let </span>compute_operation = || request_data.len();
<span class="kw">let _ </span>= response_sender.send(compute_operation()); <span class="comment">// &lt;- Send on the oneshot channel
</span>}
});
request_sender
}
<span class="kw">let </span>processor = spawn_processing_thread();
<span class="comment">// If compiled with `std` the library can receive messages with timeout on regular threads
</span><span class="attribute">#[cfg(feature = <span class="string">&quot;std&quot;</span>)] </span>{
<span class="kw">let </span>(response_sender, response_receiver) = oneshot::channel();
<span class="kw">let </span>request = Request::from(<span class="string">&quot;data from sync thread&quot;</span>);
processor.send((request, response_sender)).expect(<span class="string">&quot;Processor down&quot;</span>);
<span class="kw">match </span>response_receiver.recv_timeout(Duration::from_secs(<span class="number">1</span>)) { <span class="comment">// &lt;- Receive on the oneshot channel
</span><span class="prelude-val">Ok</span>(result) =&gt; <span class="macro">println!</span>(<span class="string">&quot;Processor returned {}&quot;</span>, result),
<span class="prelude-val">Err</span>(oneshot::RecvTimeoutError::Timeout) =&gt; <span class="macro">eprintln!</span>(<span class="string">&quot;Processor was too slow&quot;</span>),
<span class="prelude-val">Err</span>(oneshot::RecvTimeoutError::Disconnected) =&gt; <span class="macro">panic!</span>(<span class="string">&quot;Processor exited&quot;</span>),
}
}
<span class="comment">// If compiled with the `async` feature, the `Receiver` can be awaited in an async context
</span><span class="attribute">#[cfg(feature = <span class="string">&quot;async&quot;</span>)] </span>{
tokio::runtime::Runtime::new()
.unwrap()
.block_on(<span class="kw">async move </span>{
<span class="kw">let </span>(response_sender, response_receiver) = oneshot::channel();
<span class="kw">let </span>request = Request::from(<span class="string">&quot;data from sync thread&quot;</span>);
processor.send((request, response_sender)).expect(<span class="string">&quot;Processor down&quot;</span>);
<span class="kw">match </span>response_receiver.<span class="kw">await </span>{ <span class="comment">// &lt;- Receive on the oneshot channel asynchronously
</span><span class="prelude-val">Ok</span>(result) =&gt; <span class="macro">println!</span>(<span class="string">&quot;Processor returned {}&quot;</span>, result),
<span class="prelude-val">Err</span>(_e) =&gt; <span class="macro">panic!</span>(<span class="string">&quot;Processor exited&quot;</span>),
}
});
}</code></pre></div>
<h2 id="sync-vs-async"><a href="#sync-vs-async">Sync vs async</a></h2>
<p>The main motivation for writing this library was that there were no (known to me) channel
implementations allowing you to seamlessly send messages between a normal thread and an async
task, or the other way around. If message passing is the way you are communicating, of course
that should work smoothly between the sync and async parts of the program!</p>
<p>This library achieves that by having a fast and cheap send operation that can
be used in both sync threads and async tasks. The receiver has both thread blocking
receive methods for synchronous usage, and implements <code>Future</code> for asynchronous usage.</p>
<p>The receiving endpoint of this channel implements Rust’s <code>Future</code> trait and can be waited on
in an asynchronous task. This implementation is completely executor/runtime agnostic. It should
be possible to use this library with any executor.</p>
</div></details><h2 id="structs" class="small-section-header"><a href="#structs">Structs</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Receiver.html" title="oneshot::Receiver struct">Receiver</a></div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.RecvError.html" title="oneshot::RecvError struct">RecvError</a></div><div class="item-right docblock-short">An error returned from the indefinitely blocking recv functions on a [<code>Receiver</code>].</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.SendError.html" title="oneshot::SendError struct">SendError</a></div><div class="item-right docblock-short">An error returned when trying to send on a closed channel. Returned from
[<code>Sender::send</code>] if the corresponding [<code>Receiver</code>] has already been dropped.</div></div><div class="item-row"><div class="item-left module-item"><a class="struct" href="struct.Sender.html" title="oneshot::Sender struct">Sender</a></div></div></div><h2 id="enums" class="small-section-header"><a href="#enums">Enums</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="enum" href="enum.RecvTimeoutError.html" title="oneshot::RecvTimeoutError enum">RecvTimeoutError</a></div><div class="item-right docblock-short">An error returned when trying a time limited blocking receive on a [<code>Receiver</code>].</div></div><div class="item-row"><div class="item-left module-item"><a class="enum" href="enum.TryRecvError.html" title="oneshot::TryRecvError enum">TryRecvError</a></div><div class="item-right docblock-short">An error returned when trying a non blocking receive on a [<code>Receiver</code>].</div></div></div><h2 id="functions" class="small-section-header"><a href="#functions">Functions</a></h2><div class="item-table"><div class="item-row"><div class="item-left module-item"><a class="fn" href="fn.channel.html" title="oneshot::channel fn">channel</a></div><div class="item-right docblock-short">Creates a new oneshot channel and returns the two endpoints, <a href="struct.Sender.html" title="Sender"><code>Sender</code></a> and <a href="struct.Receiver.html" title="Receiver"><code>Receiver</code></a>.</div></div></div></section></div></main><div id="rustdoc-vars" data-root-path="../" data-current-crate="oneshot" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.66.0-nightly (5c8bff74b 2022-10-21)" ></div></body></html>