Sophie

Sophie

distrib > Mageia > 6 > x86_64 > media > core-updates > by-pkgid > fdedb3cf2140df9b6d419a2338ab1caa > files > 665

rust-doc-1.25.0-1.mga6.x86_64.rpm

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Sending Requests to Threads Via Channels - The Rust Programming Language</title>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <base href="">

        <link rel="stylesheet" href="book.css">
        <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
        <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

        <link rel="shortcut icon" href="favicon.png">

        <!-- Font Awesome -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme -->
        

        

        <!-- Fetch Clipboard.js from CDN but have a local fallback -->
        <script src="https://cdn.jsdelivr.net/clipboard.js/1.6.1/clipboard.min.js"></script>
        <script>
            if (typeof Clipboard == 'undefined') {
                document.write(unescape("%3Cscript src='clipboard.min.js'%3E%3C/script%3E"));
            }
        </script>

    </head>
    <body class="light">
        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } 
            if (theme === null || theme === undefined) { theme = 'light'; }
            document.body.className = theme;
            document.querySelector('html').className = theme;
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            document.querySelector('html').classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <ol class="chapter"><li><a href="ch01-00-introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><ol class="section"><li><a href="ch01-01-installation.html"><strong aria-hidden="true">1.1.</strong> Installation</a></li><li><a href="ch01-02-hello-world.html"><strong aria-hidden="true">1.2.</strong> Hello, World!</a></li><li><a href="ch01-03-how-rust-is-made-and-nightly-rust.html"><strong aria-hidden="true">1.3.</strong> How Rust is Made and “Nightly Rust”</a></li></ol></li><li><a href="ch02-00-guessing-game-tutorial.html"><strong aria-hidden="true">2.</strong> Guessing Game Tutorial</a></li><li><a href="ch03-00-common-programming-concepts.html"><strong aria-hidden="true">3.</strong> Common Programming Concepts</a></li><li><ol class="section"><li><a href="ch03-01-variables-and-mutability.html"><strong aria-hidden="true">3.1.</strong> Variables and Mutability</a></li><li><a href="ch03-02-data-types.html"><strong aria-hidden="true">3.2.</strong> Data Types</a></li><li><a href="ch03-03-how-functions-work.html"><strong aria-hidden="true">3.3.</strong> How Functions Work</a></li><li><a href="ch03-04-comments.html"><strong aria-hidden="true">3.4.</strong> Comments</a></li><li><a href="ch03-05-control-flow.html"><strong aria-hidden="true">3.5.</strong> Control Flow</a></li></ol></li><li><a href="ch04-00-understanding-ownership.html"><strong aria-hidden="true">4.</strong> Understanding Ownership</a></li><li><ol class="section"><li><a href="ch04-01-what-is-ownership.html"><strong aria-hidden="true">4.1.</strong> What is Ownership?</a></li><li><a href="ch04-02-references-and-borrowing.html"><strong aria-hidden="true">4.2.</strong> References &amp; Borrowing</a></li><li><a href="ch04-03-slices.html"><strong aria-hidden="true">4.3.</strong> Slices</a></li></ol></li><li><a href="ch05-00-structs.html"><strong aria-hidden="true">5.</strong> Using Structs to Structure Related Data</a></li><li><ol class="section"><li><a href="ch05-01-defining-structs.html"><strong aria-hidden="true">5.1.</strong> Defining and Instantiating Structs</a></li><li><a href="ch05-02-example-structs.html"><strong aria-hidden="true">5.2.</strong> An Example Program Using Structs</a></li><li><a href="ch05-03-method-syntax.html"><strong aria-hidden="true">5.3.</strong> Method Syntax</a></li></ol></li><li><a href="ch06-00-enums.html"><strong aria-hidden="true">6.</strong> Enums and Pattern Matching</a></li><li><ol class="section"><li><a href="ch06-01-defining-an-enum.html"><strong aria-hidden="true">6.1.</strong> Defining an Enum</a></li><li><a href="ch06-02-match.html"><strong aria-hidden="true">6.2.</strong> The match Control Flow Operator</a></li><li><a href="ch06-03-if-let.html"><strong aria-hidden="true">6.3.</strong> Concise Control Flow with if let</a></li></ol></li><li><a href="ch07-00-modules.html"><strong aria-hidden="true">7.</strong> Modules</a></li><li><ol class="section"><li><a href="ch07-01-mod-and-the-filesystem.html"><strong aria-hidden="true">7.1.</strong> mod and the Filesystem</a></li><li><a href="ch07-02-controlling-visibility-with-pub.html"><strong aria-hidden="true">7.2.</strong> Controlling Visibility with pub</a></li><li><a href="ch07-03-importing-names-with-use.html"><strong aria-hidden="true">7.3.</strong> Referring to Names in Different Modules</a></li></ol></li><li><a href="ch08-00-common-collections.html"><strong aria-hidden="true">8.</strong> Common Collections</a></li><li><ol class="section"><li><a href="ch08-01-vectors.html"><strong aria-hidden="true">8.1.</strong> Vectors</a></li><li><a href="ch08-02-strings.html"><strong aria-hidden="true">8.2.</strong> Strings</a></li><li><a href="ch08-03-hash-maps.html"><strong aria-hidden="true">8.3.</strong> Hash Maps</a></li></ol></li><li><a href="ch09-00-error-handling.html"><strong aria-hidden="true">9.</strong> Error Handling</a></li><li><ol class="section"><li><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong aria-hidden="true">9.1.</strong> Unrecoverable Errors with panic!</a></li><li><a href="ch09-02-recoverable-errors-with-result.html"><strong aria-hidden="true">9.2.</strong> Recoverable Errors with Result</a></li><li><a href="ch09-03-to-panic-or-not-to-panic.html"><strong aria-hidden="true">9.3.</strong> To panic! or Not To panic!</a></li></ol></li><li><a href="ch10-00-generics.html"><strong aria-hidden="true">10.</strong> Generic Types, Traits, and Lifetimes</a></li><li><ol class="section"><li><a href="ch10-01-syntax.html"><strong aria-hidden="true">10.1.</strong> Generic Data Types</a></li><li><a href="ch10-02-traits.html"><strong aria-hidden="true">10.2.</strong> Traits: Defining Shared Behavior</a></li><li><a href="ch10-03-lifetime-syntax.html"><strong aria-hidden="true">10.3.</strong> Validating References with Lifetimes</a></li></ol></li><li><a href="ch11-00-testing.html"><strong aria-hidden="true">11.</strong> Testing</a></li><li><ol class="section"><li><a href="ch11-01-writing-tests.html"><strong aria-hidden="true">11.1.</strong> Writing tests</a></li><li><a href="ch11-02-running-tests.html"><strong aria-hidden="true">11.2.</strong> Running tests</a></li><li><a href="ch11-03-test-organization.html"><strong aria-hidden="true">11.3.</strong> Test Organization</a></li></ol></li><li><a href="ch12-00-an-io-project.html"><strong aria-hidden="true">12.</strong> An I/O Project: Building a Command Line Program</a></li><li><ol class="section"><li><a href="ch12-01-accepting-command-line-arguments.html"><strong aria-hidden="true">12.1.</strong> Accepting Command Line Arguments</a></li><li><a href="ch12-02-reading-a-file.html"><strong aria-hidden="true">12.2.</strong> Reading a File</a></li><li><a href="ch12-03-improving-error-handling-and-modularity.html"><strong aria-hidden="true">12.3.</strong> Refactoring to Improve Modularity and Error Handling</a></li><li><a href="ch12-04-testing-the-librarys-functionality.html"><strong aria-hidden="true">12.4.</strong> Developing the Library’s Functionality with Test Driven Development</a></li><li><a href="ch12-05-working-with-environment-variables.html"><strong aria-hidden="true">12.5.</strong> Working with Environment Variables</a></li><li><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong aria-hidden="true">12.6.</strong> Writing Error Messages to Standard Error Instead of Standard Output</a></li></ol></li><li><a href="ch13-00-functional-features.html"><strong aria-hidden="true">13.</strong> Functional Language Features: Iterators and Closures</a></li><li><ol class="section"><li><a href="ch13-01-closures.html"><strong aria-hidden="true">13.1.</strong> Closures: Anonymous Functions that Can Capture Their Environment</a></li><li><a href="ch13-02-iterators.html"><strong aria-hidden="true">13.2.</strong> Processing a Series of Items with Iterators</a></li><li><a href="ch13-03-improving-our-io-project.html"><strong aria-hidden="true">13.3.</strong> Improving Our I/O Project</a></li><li><a href="ch13-04-performance.html"><strong aria-hidden="true">13.4.</strong> Comparing Performance: Loops vs. Iterators</a></li></ol></li><li><a href="ch14-00-more-about-cargo.html"><strong aria-hidden="true">14.</strong> More about Cargo and Crates.io</a></li><li><ol class="section"><li><a href="ch14-01-release-profiles.html"><strong aria-hidden="true">14.1.</strong> Customizing Builds with Release Profiles</a></li><li><a href="ch14-02-publishing-to-crates-io.html"><strong aria-hidden="true">14.2.</strong> Publishing a Crate to Crates.io</a></li><li><a href="ch14-03-cargo-workspaces.html"><strong aria-hidden="true">14.3.</strong> Cargo Workspaces</a></li><li><a href="ch14-04-installing-binaries.html"><strong aria-hidden="true">14.4.</strong> Installing Binaries from Crates.io with cargo install</a></li><li><a href="ch14-05-extending-cargo.html"><strong aria-hidden="true">14.5.</strong> Extending Cargo with Custom Commands</a></li></ol></li><li><a href="ch15-00-smart-pointers.html"><strong aria-hidden="true">15.</strong> Smart Pointers</a></li><li><ol class="section"><li><a href="ch15-01-box.html"><strong aria-hidden="true">15.1.</strong> Box<T> Points to Data on the Heap and Has a Known Size</a></li><li><a href="ch15-02-deref.html"><strong aria-hidden="true">15.2.</strong> The Deref Trait Allows Access to the Data Through a Reference</a></li><li><a href="ch15-03-drop.html"><strong aria-hidden="true">15.3.</strong> The Drop Trait Runs Code on Cleanup</a></li><li><a href="ch15-04-rc.html"><strong aria-hidden="true">15.4.</strong> Rc<T>, the Reference Counted Smart Pointer</a></li><li><a href="ch15-05-interior-mutability.html"><strong aria-hidden="true">15.5.</strong> RefCell<T> and the Interior Mutability Pattern</a></li><li><a href="ch15-06-reference-cycles.html"><strong aria-hidden="true">15.6.</strong> Creating Reference Cycles and Leaking Memory is Safe</a></li></ol></li><li><a href="ch16-00-concurrency.html"><strong aria-hidden="true">16.</strong> Fearless Concurrency</a></li><li><ol class="section"><li><a href="ch16-01-threads.html"><strong aria-hidden="true">16.1.</strong> Threads</a></li><li><a href="ch16-02-message-passing.html"><strong aria-hidden="true">16.2.</strong> Message Passing</a></li><li><a href="ch16-03-shared-state.html"><strong aria-hidden="true">16.3.</strong> Shared State</a></li><li><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong aria-hidden="true">16.4.</strong> Extensible Concurrency: Sync and Send</a></li></ol></li><li><a href="ch17-00-oop.html"><strong aria-hidden="true">17.</strong> Is Rust an Object-Oriented Programming Language?</a></li><li><ol class="section"><li><a href="ch17-01-what-is-oo.html"><strong aria-hidden="true">17.1.</strong> What Does Object-Oriented Mean?</a></li><li><a href="ch17-02-trait-objects.html"><strong aria-hidden="true">17.2.</strong> Trait Objects for Using Values of Different Types</a></li><li><a href="ch17-03-oo-design-patterns.html"><strong aria-hidden="true">17.3.</strong> Object-Oriented Design Pattern Implementations</a></li></ol></li><li><a href="ch18-00-patterns.html"><strong aria-hidden="true">18.</strong> Patterns Match the Structure of Values</a></li><li><ol class="section"><li><a href="ch18-01-all-the-places-for-patterns.html"><strong aria-hidden="true">18.1.</strong> All the Places Patterns May be Used</a></li><li><a href="ch18-02-refutability.html"><strong aria-hidden="true">18.2.</strong> Refutability: Whether a Pattern Might Fail to Match</a></li><li><a href="ch18-03-pattern-syntax.html"><strong aria-hidden="true">18.3.</strong> All the Pattern Syntax</a></li></ol></li><li><a href="ch19-00-advanced-features.html"><strong aria-hidden="true">19.</strong> Advanced Features</a></li><li><ol class="section"><li><a href="ch19-01-unsafe-rust.html"><strong aria-hidden="true">19.1.</strong> Unsafe Rust</a></li><li><a href="ch19-02-advanced-lifetimes.html"><strong aria-hidden="true">19.2.</strong> Advanced Lifetimes</a></li><li><a href="ch19-03-advanced-traits.html"><strong aria-hidden="true">19.3.</strong> Advanced Traits</a></li><li><a href="ch19-04-advanced-types.html"><strong aria-hidden="true">19.4.</strong> Advanced Types</a></li><li><a href="ch19-05-advanced-functions-and-closures.html"><strong aria-hidden="true">19.5.</strong> Advanced Functions &amp; Closures</a></li></ol></li><li><a href="ch20-00-final-project-a-web-server.html"><strong aria-hidden="true">20.</strong> Final Project: Building a Multithreaded Web Server</a></li><li><ol class="section"><li><a href="ch20-01-single-threaded.html"><strong aria-hidden="true">20.1.</strong> A Single Threaded Web Server</a></li><li><a href="ch20-02-slow-requests.html"><strong aria-hidden="true">20.2.</strong> How Slow Requests Affect Throughput</a></li><li><a href="ch20-03-designing-the-interface.html"><strong aria-hidden="true">20.3.</strong> Designing the Thread Pool Interface</a></li><li><a href="ch20-04-storing-threads.html"><strong aria-hidden="true">20.4.</strong> Creating the Thread Pool and Storing Threads</a></li><li><a href="ch20-05-sending-requests-via-channels.html" class="active"><strong aria-hidden="true">20.5.</strong> Sending Requests to Threads Via Channels</a></li><li><a href="ch20-06-graceful-shutdown-and-cleanup.html"><strong aria-hidden="true">20.6.</strong> Graceful Shutdown and Cleanup</a></li></ol></li><li><a href="appendix-00.html"><strong aria-hidden="true">21.</strong> Appendix</a></li><li><ol class="section"><li><a href="appendix-01-keywords.html"><strong aria-hidden="true">21.1.</strong> A - Keywords</a></li><li><a href="appendix-02-operators.html"><strong aria-hidden="true">21.2.</strong> B - Operators and Symbols</a></li><li><a href="appendix-03-derivable-traits.html"><strong aria-hidden="true">21.3.</strong> C - Derivable Traits</a></li><li><a href="appendix-04-macros.html"><strong aria-hidden="true">21.4.</strong> D - Macros</a></li><li><a href="appendix-05-translation.html"><strong aria-hidden="true">21.5.</strong> E - Translations</a></li><li><a href="appendix-06-newest-features.html"><strong aria-hidden="true">21.6.</strong> F - Newest Features</a></li></ol></li></ol>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar" class="menu-bar">
                    <div id="menu-bar-sticky-container">
                        <div class="left-buttons">
                            <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                                <i class="fa fa-bars"></i>
                            </button>
                            <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                                <i class="fa fa-paint-brush"></i>
                            </button>
                            <ul id="theme-list" class="theme-popup" aria-label="submenu">
                                <li><button class="theme" id="light">Light <span class="default">(default)</span></button></li>
                                <li><button class="theme" id="rust">Rust</button></li>
                                <li><button class="theme" id="coal">Coal</button></li>
                                <li><button class="theme" id="navy">Navy</button></li>
                                <li><button class="theme" id="ayu">Ayu</button></li>
                            </ul>
                        </div>

                        <h1 class="menu-title">The Rust Programming Language</h1>

                        <div class="right-buttons">
                            <a href="print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                        </div>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <a class="header" href="ch20-05-sending-requests-via-channels.html#sending-requests-to-threads-via-channels" id="sending-requests-to-threads-via-channels"><h2>Sending Requests to Threads Via Channels</h2></a>
<p>The next problem to tackle is that our closures do absolutely nothing. We’ve
been working around the problem that we get the actual closure we want to
execute in the <code>execute</code> method, but it feels like we need to know the actual
closures when we create the <code>ThreadPool</code>.</p>
<p>Let’s think about what we really want to do though: we want the <code>Worker</code>
structs that we just created to fetch jobs from a queue that the <code>ThreadPool</code>
holds, and run those jobs in a thread.</p>
<p>In Chapter 16, we learned about channels. Channels are a great way to
communicate between two threads, and they’re perfect for this use-case. The
channel will function as the queue of jobs, and <code>execute</code> will send a job from
the <code>ThreadPool</code> to the <code>Worker</code> instances that are checking for jobs in the
thread they’ve spawned. Here’s the plan:</p>
<ol>
<li><code>ThreadPool</code> will create a channel and hold on to the sending side.</li>
<li>Each <code>Worker</code> will hold on to the receiving side of the channel.</li>
<li>A new <code>Job</code> struct will hold the closures we want to send down the channel.</li>
<li>The <code>execute</code> method of <code>ThreadPool</code> will send the job it wants
to execute down the sending side of the channel.</li>
<li>In a thread, the <code>Worker</code> will loop over its receiving side of the channel
and execute the closures of any jobs it receives.</li>
</ol>
<p>Let’s start by creating a channel in <code>ThreadPool::new</code> and holding the sending
side in the <code>ThreadPool</code> instance, as shown in Listing 20-16. <code>Job</code> is the type
of item we’re going to be sending down the channel; it’s a struct that doesn’t
hold anything for now:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
# use std::thread;
// --snip--
use std::sync::mpsc;

pub struct ThreadPool {
    workers: Vec&lt;Worker&gt;,
    sender: mpsc::Sender&lt;Job&gt;,
}

struct Job;

impl ThreadPool {
    // --snip--
    pub fn new(size: usize) -&gt; ThreadPool {
        assert!(size &gt; 0);

        let (sender, receiver) = mpsc::channel();

        let mut workers = Vec::with_capacity(size);

        for id in 0..size {
            workers.push(Worker::new(id));
        }

        ThreadPool {
            workers,
            sender,
        }
    }
    // --snip--
}
#
# struct Worker {
#     id: usize,
#     thread: thread::JoinHandle&lt;()&gt;,
# }
#
# impl Worker {
#     fn new(id: usize) -&gt; Worker {
#         let thread = thread::spawn(|| {});
#
#         Worker {
#             id,
#             thread,
#         }
#     }
# }
#}</code></pre></pre>
<p><span class="caption">Listing 20-16: Modifying <code>ThreadPool</code> to store the
sending end of a channel that sends <code>Job</code> instances</span></p>
<p>In <code>ThreadPool::new</code>, we create our new channel, and then have the pool hang on
to the sending end. This will successfully compile, still with warnings.</p>
<p>Let’s try passing a receiving end of the channel into each worker when the
thread pool creates them. We know we want to use the receiving end of the
channel in the thread that the workers spawn, so we’re going to reference the
<code>receiver</code> parameter in the closure. The code shown here in Listing 20-17
won’t quite compile yet:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">impl ThreadPool {
    // --snip--
    pub fn new(size: usize) -&gt; ThreadPool {
        assert!(size &gt; 0);

        let (sender, receiver) = mpsc::channel();

        let mut workers = Vec::with_capacity(size);

        for id in 0..size {
            workers.push(Worker::new(id, receiver));
        }

        ThreadPool {
            workers,
            sender,
        }
    }
    // --snip--
}

// --snip--

impl Worker {
    fn new(id: usize, receiver: mpsc::Receiver&lt;Job&gt;) -&gt; Worker {
        let thread = thread::spawn(|| {
            receiver;
        });

        Worker {
            id,
            thread,
        }
    }
}
</code></pre>
<p><span class="caption">Listing 20-17: Passing the receiving end of the channel
to the workers</span></p>
<p>These are small and straightforward changes: we pass in the receiving end of
the channel into <code>Worker::new</code>, and then we use it inside of the closure.</p>
<p>If we try to check this, we get this error:</p>
<pre><code class="language-text">$ cargo check
   Compiling hello v0.1.0 (file:///projects/hello)
error[E0382]: use of moved value: `receiver`
  --&gt; src/lib.rs:27:42
   |
27 |             workers.push(Worker::new(id, receiver));
   |                                          ^^^^^^^^ value moved here in
   previous iteration of loop
   |
   = note: move occurs because `receiver` has type
   `std::sync::mpsc::Receiver&lt;Job&gt;`, which does not implement the `Copy` trait
</code></pre>
<p>The code as written won’t quite work since it’s trying to pass <code>receiver</code> to
multiple <code>Worker</code> instances. Recall from Chapter 16 that the channel
implementation provided by Rust is multiple <em>producer</em>, single <em>consumer</em>, so
we can’t just clone the consuming end of the channel to fix this. We also don’t
want to clone the consuming end even if we wanted to; sharing the single
<code>receiver</code> between all of the workers is the mechanism by which we’d like to
distribute the jobs across the threads.</p>
<p>Additionally, taking a job off the channel queue involves mutating <code>receiver</code>,
so the threads need a safe way to share <code>receiver</code> and be allowed to modify it.
If the modifications weren’t thread-safe, we might get race conditions such as
two threads executing the same job if they both take the same job off the queue
at the same time.</p>
<p>So remembering the thread-safe smart pointers that we discussed in Chapter 16,
in order to share ownership across multiple threads and allow the threads to
mutate the value, we need to use <code>Arc&lt;Mutex&lt;T&gt;&gt;</code>. <code>Arc</code> will let multiple
workers own the receiver, and <code>Mutex</code> will make sure that only one worker is
getting a job from the receiver at a time. Listing 20-18 shows the changes we
need to make:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
# use std::thread;
# use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;

// --snip--

# pub struct ThreadPool {
#     workers: Vec&lt;Worker&gt;,
#     sender: mpsc::Sender&lt;Job&gt;,
# }
# struct Job;
#
impl ThreadPool {
    // --snip--
    pub fn new(size: usize) -&gt; ThreadPool {
        assert!(size &gt; 0);

        let (sender, receiver) = mpsc::channel();

        let receiver = Arc::new(Mutex::new(receiver));

        let mut workers = Vec::with_capacity(size);

        for id in 0..size {
            workers.push(Worker::new(id, Arc::clone(&amp;receiver)));
        }

        ThreadPool {
            workers,
            sender,
        }
    }

    // --snip--
}
# struct Worker {
#     id: usize,
#     thread: thread::JoinHandle&lt;()&gt;,
# }
#
impl Worker {
    fn new(id: usize, receiver: Arc&lt;Mutex&lt;mpsc::Receiver&lt;Job&gt;&gt;&gt;) -&gt; Worker {
        // --snip--
#         let thread = thread::spawn(|| {
#            receiver;
#         });
#
#         Worker {
#             id,
#             thread,
#         }
    }
}
#}</code></pre></pre>
<p><span class="caption">Listing 20-18: Sharing the receiving end of the channel
between the workers by using <code>Arc</code> and <code>Mutex</code></span></p>
<p>In <code>ThreadPool::new</code>, we put the receiving end of the channel in an <code>Arc</code> and a
<code>Mutex</code>. For each new worker, we clone the <code>Arc</code> to bump the reference count so
the workers can share ownership of the receiving end.</p>
<p>With these changes, the code compiles! We’re getting there!</p>
<p>Let’s finally implement the <code>execute</code> method on <code>ThreadPool</code>. We’re also going
to change the <code>Job</code> struct: instead of being a struct, <code>Job</code> is going to be a
type alias for a trait object that holds the type of closure that <code>execute</code>
receives. We discussed how type aliases can help make long types shorter, and
this is such a case! Take a look at Listing 20-19:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
// --snip--
# pub struct ThreadPool {
#     workers: Vec&lt;Worker&gt;,
#     sender: mpsc::Sender&lt;Job&gt;,
# }
# use std::sync::mpsc;
# struct Worker {}

type Job = Box&lt;FnOnce() + Send + 'static&gt;;

impl ThreadPool {
    // --snip--

    pub fn execute&lt;F&gt;(&amp;self, f: F)
        where
            F: FnOnce() + Send + 'static
    {
        let job = Box::new(f);

        self.sender.send(job).unwrap();
    }
}

// --snip--
#}</code></pre></pre>
<p><span class="caption">Listing 20-19: Creating a <code>Job</code> type alias for a <code>Box</code>
that holds each closure, then sending the job down the channel</span></p>
<p>After creating a new <code>Job</code> instance using the closure we get in
<code>execute</code>, we send that job down the sending end of the channel. We’re calling
<code>unwrap</code> on <code>send</code> since sending may fail if the receiving end has stopped
receiving new messages, which would happen if we stop all of our threads from
executing. This isn’t possible right now, though, since our threads continue
executing as long as the pool exists. We use <code>unwrap</code> since we know the failure
case won’t happen even though the compiler can’t tell that, which is an
appropriate use of <code>unwrap</code> as we discussed in Chapter 9.</p>
<p>Are we done yet? Not quite! In the worker, we’ve still got a closure being
passed to <code>thread::spawn</code> that only <em>references</em> the receiving end of the
channel. Instead, we need the closure to loop forever, asking the receiving end
of the channel for a job, and running the job when it gets one. Let’s make the
change shown in Listing 20-20 to <code>Worker::new</code>:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">// --snip--

impl Worker {
    fn new(id: usize, receiver: Arc&lt;Mutex&lt;mpsc::Receiver&lt;Job&gt;&gt;&gt;) -&gt; Worker {
        let thread = thread::spawn(move || {
            loop {
                let job = receiver.lock().unwrap().recv().unwrap();

                println!(&quot;Worker {} got a job; executing.&quot;, id);

                (*job)();
            }
        });

        Worker {
            id,
            thread,
        }
    }
}
</code></pre>
<p><span class="caption">Listing 20-20: Receiving and executing the jobs in the
worker’s thread</span></p>
<p>Here, we first call <code>lock</code> on the <code>receiver</code> to acquire the mutex, then
<code>unwrap</code> to panic on any errors. Acquiring a lock might fail if the mutex is in
a state called <em>poisoned</em>, which can happen if some other thread panicked while
holding the lock rather than releasing it. If this thread can’t get the lock
for that reason, calling <code>unwrap</code> to have this thread panic is the correct
action to take as well. Feel free to change this <code>unwrap</code> to an <code>expect</code> with
an error message that is meaningful to you if you’d like.</p>
<p>If we get the lock on the mutex, then we call <code>recv</code> to receive a <code>Job</code> from
the channel. A final <code>unwrap</code> moves past those errors as well. <code>recv</code> will
return <code>Err</code> if the thread holding the sending side of the channel has shut
down, similar to how the <code>send</code> method returns <code>Err</code> if the receiving side
shuts down.</p>
<p>The call to <code>recv</code> blocks; that is, if there’s no job yet, this thread will sit
here until a job becomes available. The <code>Mutex&lt;T&gt;</code> makes sure that only one
<code>Worker</code> thread at a time is trying to request a job.</p>
<p>Theoretically, this code should compile. Unfortunately, the Rust compiler isn’t
perfect yet, and we get this error:</p>
<pre><code class="language-text">error[E0161]: cannot move a value of type std::ops::FnOnce() +
std::marker::Send: the size of std::ops::FnOnce() + std::marker::Send cannot be
statically determined
  --&gt; src/lib.rs:63:17
   |
63 |                 (*job)();
   |                 ^^^^^^
</code></pre>
<p>This error is fairly cryptic, and that’s because the problem is fairly cryptic.
In order to call a <code>FnOnce</code> closure that is stored in a <code>Box&lt;T&gt;</code> (which is what
our <code>Job</code> type alias is), the closure needs to be able to move itself out of
the <code>Box&lt;T&gt;</code> since when we call the closure, it takes ownership of <code>self</code>. In
general, moving a value out of a <code>Box&lt;T&gt;</code> isn’t allowed since Rust doesn’t know
how big the value inside the <code>Box&lt;T&gt;</code> is going to be; recall in Chapter 15 that
we used <code>Box&lt;T&gt;</code> precisely because we had something of an unknown size that we
wanted to store in a <code>Box&lt;T&gt;</code> to get a value of a known size.</p>
<p>We saw in Chapter 17, Listing 17-15 that we can write methods that use the
syntax <code>self: Box&lt;Self&gt;</code> so that the method takes ownership of a <code>Self</code> value
that is stored in a <code>Box&lt;T&gt;</code>. That’s what we want to do here, but unfortunately
the part of Rust that implements what happens when we call a closure isn’t
implemented using <code>self: Box&lt;Self&gt;</code>. So Rust doesn’t yet understand that it
could use <code>self: Box&lt;Self&gt;</code> in this situation in order to take ownership of the
closure and move the closure out of the <code>Box&lt;T&gt;</code>.</p>
<p>In the future, the code in Listing 20-20 should work just fine. Rust is still a
work in progress with places that the compiler could be improved. There are
people just like you working to fix this and other issues! Once you’ve finished
the book, we would love for you to join in.</p>
<p>But for now, let’s work around this problem. Luckily, there’s a trick that
involves telling Rust explicitly that we’re in a case where we can take
ownership of the value inside the <code>Box&lt;T&gt;</code> using <code>self: Box&lt;Self&gt;</code>, and once we
have ownership of the closure, we can call it. This involves defining a new
trait that has a method <code>call_box</code> that uses <code>self: Box&lt;Self&gt;</code> in its
signature, defining that trait for any type that implements <code>FnOnce()</code>,
changing our type alias to use the new trait, and changing <code>Worker</code> to use the
<code>call_box</code> method. These changes are shown in Listing 20-21:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">trait FnBox {
    fn call_box(self: Box&lt;Self&gt;);
}

impl&lt;F: FnOnce()&gt; FnBox for F {
    fn call_box(self: Box&lt;F&gt;) {
        (*self)()
    }
}

type Job = Box&lt;FnBox + Send + 'static&gt;;

// --snip--

impl Worker {
    fn new(id: usize, receiver: Arc&lt;Mutex&lt;mpsc::Receiver&lt;Job&gt;&gt;&gt;) -&gt; Worker {
        let thread = thread::spawn(move || {
            loop {
                let job = receiver.lock().unwrap().recv().unwrap();

                println!(&quot;Worker {} got a job; executing.&quot;, id);

                job.call_box();
            }
        });

        Worker {
            id,
            thread,
        }
    }
}
</code></pre>
<p><span class="caption">Listing 20-21: Adding a new trait <code>FnBox</code> to work around
the current limitations of <code>Box&lt;FnOnce()&gt;</code></span></p>
<p>First, we create a new trait named <code>FnBox</code>. This trait has one method,
<code>call_box</code>, similar to the <code>call</code> methods on the other <code>Fn*</code> traits, except
this method takes <code>self: Box&lt;Self&gt;</code> in order to take ownership of <code>self</code> and
move the value out of the <code>Box&lt;T&gt;</code>.</p>
<p>Next, we implement the <code>FnBox</code> trait for any type <code>F</code> that implements the
<code>FnOnce()</code> trait. Effectively, this means that any <code>FnOnce()</code> closures can use
our <code>call_box</code> method. The implementation of <code>call_box</code> uses <code>(*self)()</code> to
move the closure out of the <code>Box&lt;T&gt;</code> and call the closure.</p>
<p>Instead of <code>FnOnce()</code>, we now want our <code>Job</code> type alias to be a <code>Box</code> of
anything that implements our new trait <code>FnBox</code>. This will allow us to use
<code>call_box</code> in <code>Worker</code> when we get a <code>Job</code> value. Because we implemented the
<code>FnBox</code> trait for any <code>FnOnce()</code> closure, we don’t have to change anything
about the actual values we’re sending down the channel.</p>
<p>Finally, in the closure run in the thread in <code>Worker::new</code>, we use <code>call_box</code>
instead of invoking the closure directly. Now Rust is able to understand that
what we want to do is fine.</p>
<p>This is a very sneaky, complicated trick. Don’t worry too much if it doesn’t
make perfect sense; someday, it will be completely unnecessary.</p>
<p>With this trick, our thread pool is in a working state! Give it a <code>cargo run</code>,
and make some requests:</p>
<pre><code class="language-text">$ cargo run
   Compiling hello v0.1.0 (file:///projects/hello)
warning: field is never used: `workers`
 --&gt; src/lib.rs:7:5
  |
7 |     workers: Vec&lt;Worker&gt;,
  |     ^^^^^^^^^^^^^^^^^^^^
  |
  = note: #[warn(dead_code)] on by default

warning: field is never used: `id`
  --&gt; src/lib.rs:61:5
   |
61 |     id: usize,
   |     ^^^^^^^^^
   |
   = note: #[warn(dead_code)] on by default

warning: field is never used: `thread`
  --&gt; src/lib.rs:62:5
   |
62 |     thread: thread::JoinHandle&lt;()&gt;,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(dead_code)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.99 secs
     Running `target/debug/hello`
     Worker 0 got a job; executing.
Worker 2 got a job; executing.
Worker 1 got a job; executing.
Worker 3 got a job; executing.
Worker 0 got a job; executing.
Worker 2 got a job; executing.
Worker 1 got a job; executing.
Worker 3 got a job; executing.
Worker 0 got a job; executing.
Worker 2 got a job; executing.
</code></pre>
<p>Success! We now have a thread pool executing connections asynchronously. We
never create more than four threads, so our system won’t get overloaded if the
server gets a lot of requests. If we make a request to <code>/sleep</code>, the server
will be able to serve other requests by having another thread run them.</p>
<p>What about those warnings, though? Don’t we use the <code>workers</code>, <code>id</code>, and
<code>thread</code> fields? Well, right now, we’re using all three of these fields to hold
onto some data, but we don’t actually <em>do</em> anything with the data once we’ve
set up the thread pool and started running the code that sends jobs down the
channel to the threads. If we didn’t hold onto these values, though, they’d go
out of scope: for example, if we didn’t return the <code>Vec&lt;Worker&gt;</code> value as part
of the <code>ThreadPool</code>, the vector would get cleaned up at the end of
<code>ThreadPool::new</code>.</p>
<p>So are these warnings wrong? In one sense yes, the warnings are wrong, since we
are using the fields to store data we need to keep around. In another sense,
no, the warnings aren’t wrong, and they’re telling us that we’ve forgotten to
do something: we never do anything to clean up our thread pool once it’s done
being used, we just use <span class="keystroke">ctrl-C</span> to stop the
program and let the operating system clean up after us. Let’s implement a
graceful shutdown that cleans up everything we’ve created instead.</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="ch20-04-storing-threads.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        

                        
                            <a rel="next" href="ch20-06-graceful-shutdown-and-cleanup.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                
                    <a href="ch20-04-storing-threads.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a href="ch20-06-graceful-shutdown-and-cleanup.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                
            </nav>

        </div>


        <!-- Local fallback for Font Awesome -->
        <script>
            if (getComputedStyle(document.querySelector(".fa")).fontFamily !== "FontAwesome") {
                var link = document.createElement('link');
                link.rel = 'stylesheet';
                link.type = 'text/css';
                link.href = '_FontAwesome/css/font-awesome.css';
                document.head.insertBefore(link, document.head.firstChild)
            }
        </script>

        

        

        

        

        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS script -->
        

    </body>
</html>