3

I'm trying to make this example work

use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread;
use std::sync::Arc;

struct User {
    reference: String,
    email: String
}

struct UserIndex {
    reference: usize,
    email: usize
}

fn main() {

    let rows = vec![
        vec!["abcd", "[email protected]"],
        vec!["efgh", "[email protected]"],
        vec!["wfee", "[email protected]"],
        vec!["rrgr", "[email protected]"]
    ];

    let user_index = Arc::new(
        UserIndex {
            reference: 0,
            email: 1
        }
    );

    let chunk_len = (rows.len() / 2) as usize;
    let mut chunks = Vec::new();
    for chunk in rows.chunks(chunk_len) {
        chunks.push(chunk.to_owned());
    }

    let (tx, rx): (Sender<Vec<User>>, Receiver<Vec<User>>) = mpsc::channel();

    for chunk in chunks {
        let thread_tx = tx.clone();
        thread::spawn(move || {
            let user_index_cloned = user_index.clone();
            let result = chunk.iter().map( |row|
                User {
                    reference: row[user_index_cloned.reference].to_string(),
                    email: row[user_index_cloned.email].to_string()
                }
            ).collect::<Vec<User>>();
            thread_tx.send(result).unwrap();
        });
    }

    let mut users = Vec::new();
    for _ in 0..chunk_len {
        users.push(rx.recv());
    }

}

but it's throwing an error

src/main.rs:43:28: 43:38 error: capture of moved value: `user_index` [E0382]
src/main.rs:43          let user_index_cloned = user_index.clone();
                                                ^~~~~~~~~~
note: in expansion of closure expansion
src/main.rs:42:17: 51:4 note: expansion site
note: in expansion of for loop expansion
src/main.rs:40:2: 52:3 note: expansion site
src/main.rs:42:17: 51:4 note: `user_index` moved into closure environment here because it has type `[closure(())]`, which is non-copyable
src/main.rs:42      thread::spawn(move || {
src/main.rs:43          let user_index_cloned = user_index.clone();
src/main.rs:44          let result = chunk.iter().map( |row|
src/main.rs:45              User {
src/main.rs:46                  reference: row[user_index_cloned.reference].to_string(),
src/main.rs:47                  email: row[user_index_cloned.email].to_string()
               ...
note: in expansion of closure expansion
src/main.rs:42:17: 51:4 note: expansion site
note: in expansion of for loop expansion
src/main.rs:40:2: 52:3 note: expansion site
src/main.rs:42:17: 51:4 help: perhaps you meant to use `clone()`?
error: aborting due to previous error

now according to this discussion it should have worked, but it doesn't. What am I missing here?

1 Answer 1

5

You're almost there. It's just that Arc has to be cloned outside of the spawned thread:

for chunk in chunks {
    let thread_tx = tx.clone();
    let user_index_cloned = user_index.clone();
    thread::spawn(move || {
        let result = chunk.iter().map( |row|
            User {
                reference: row[user_index_cloned.reference].to_string(),
                email: row[user_index_cloned.email].to_string()
            }
        ).collect::<Vec<User>>();
        thread_tx.send(result).unwrap();
    });
}

This has to be done because otherwise user_index indeed will be moved into the thread, and doing this in a loop is a violation of ownership rules.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.