Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Trouble for "move" when I tried use multiple thread

I am new for rust and I get some move trouble when I want to use multiple thread to do something; and it seems I can’t "real" copy some data;

use std::collections::HashMap;
use std::sync::mpsc;
use std::thread;


pub fn frequency(input: &str, some_chars: Vec<char>){
    let all_chars = input.chars();
    let mut  unique_chars = vec![];
    for ci in all_chars {
        if ! unique_chars.contains(&ci) {
            unique_chars.push(ci);
        }
    }
    let (tx, rx) = mpsc::channel();

    for tci in some_chars {
        let tx_copy = tx.clone();
        thread::spawn(move || {
            let mut chars_count= 0 as usize;
            let all_chars_copy = all_chars.clone();
            for aci in all_chars_copy {
                if aci == tci {
                    chars_count += 1;
                }
            }
            tx_copy.send((tci, chars_count));
        });
    }

    for received in rx {
        println!("Got: {:?}", received);
    }

}


fn main() {
    let a_string = "dsfsdfdsfsdfsdfsdfsdfw4eer34fdefd";
    frequency(a_string, vec!['a', 'b', 'c']);
}

The compile error is as below; when I want to move some data on mutiple thread, i should copy some data to "move", but it seems look like failed; shall I get some advice for resolve this problem?

error[E0521]: borrowed data escapes outside of function
  --> src\main.rs:18:9
   |
6  |   pub fn frequency(input: &str, some_chars: Vec<char>){
   |                    -----  - let's call the lifetime of this reference `'1`
   |                    |
   |                    `input` is a reference that is only valid in the function body
...
18 | /         thread::spawn(move || {
19 | |             let mut chars_count= 0 as usize;
20 | |             let all_chars_copy = all_chars.clone();
21 | |             for aci in all_chars_copy {
...  |
26 | |             tx_copy.send((tci, chars_count));
27 | |         });
   | |          ^
   | |          |
   | |__________`input` escapes the function body here
   |            argument requires that `'1` must outlive `'static`

error[E0382]: use of moved value: `all_chars`

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Your code has multiple issues:

  1. You already move all_chars before you even start the first thread here:
for ci in all_chars {

Since it’s cheap you can just create a new one like this:

for ci in input.chars() {
  1. Your’e trying to clone all_chars inside of the closure but at that point you already moved it, so either clone it outside:
        thread::spawn({
            let all_chars = all_chars.clone();
            move || {
                let mut chars_count = 0 as usize;
                for aci in all_chars {
                    if aci == tci {
                        chars_count += 1;
                    }
                }
                tx_copy.send((tci, chars_count));
            }
        });

or just create it from scratch again:

        thread::spawn(move || {
                let mut chars_count = 0 as usize;
                for aci in input.chars() {
                    if aci == tci {
                        chars_count += 1;
                    }
                }
                tx_copy.send((tci, chars_count));
            }
);
  1. You get bitten by the fact that you’re using .chars() borrows the original &str so it’s referencing local variables, to overcome that you can just use thread::scope because you read the contents of the threads at the end of the function anyways:
use std::collections::HashMap;
use std::sync::mpsc;
use std::thread;

pub fn frequency(input: &str, some_chars: Vec<char>) {
    let mut unique_chars = vec![];
    for ci in input.chars() {
        if !unique_chars.contains(&ci) {
            unique_chars.push(ci);
        }
    }
    let (tx, rx) = mpsc::channel();

    thread::scope(|s| {
        for tci in some_chars {
            let tx_copy = tx.clone();
            s.spawn(move || {
                let mut chars_count = 0 as usize;
                for aci in input.chars() {
                    if aci == tci {
                        chars_count += 1;
                    }
                }
                tx_copy.send((tci, chars_count));
            });
        }
    });

    for received in rx {
        println!("Got: {:?}", received);
    }
}
  1. Of course Masklinn is right you don’t need the channel at all.
use std::thread;

pub fn frequency(input: &str, some_chars: Vec<char>) {
    let mut unique_chars = vec![];
    for ci in input.chars() {
        if !unique_chars.contains(&ci) {
            unique_chars.push(ci);
        }
    }

    thread::scope(|s| {
        let mut ts = Vec::with_capacity(some_chars.len());
        for tci in some_chars {
            ts.push(s.spawn(move || {
                let mut chars_count = 0 as usize;
                for aci in input.chars() {
                    if aci == tci {
                        chars_count += 1;
                    }
                }
                (tci, chars_count)
            }));
        }
        for h in ts {
            let (tci, chars_count) = h.join().unwrap();
            println!("Got: {:?}", (tci, chars_count));
        }
    });
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading