Would like some comment on my newbie code


#1

I am new to Rust. Here is the sample code for the exercise:

Construct a shared_channel.rs program that lets any number of threads share a channel to send in a value and has one receiver that collects all the values. As a hint, use clone() to give each thread access to the sending tx endpoint. (Refer to the example code in Chapter 8/exercises/shared_channel.rs.) from the book Rust Essentials chapter 8. Concurrency and Parallelism.

I would appreciate comment on the solution I came with:

use std::error::Error;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;

static SENDER_QTY:usize = 20;

type Sending = i32;
type _Sender = Sender<Sending>;
type _Receiver = Receiver<Sending>;
type VecSender = Vec<Sender<Sending>>;


fn main() {
  let (sender, reader) = channel();  
  let senders = make_senders(sender);
  send(senders);
  read(reader);
}


fn make_senders(sender_to_clone: _Sender) -> VecSender {
  let mut result: VecSender = Vec::with_capacity(SENDER_QTY);
  for _ in 0..SENDER_QTY  {
    result.push(sender_to_clone.clone()); 
  }

  result
}


fn send(senders: VecSender) {
  for sender in &senders {
    send_something(sender);
  }
}


fn send_something(sender: &_Sender) {
  let values = [12, 56, 5, 12];
  for i in 0..values.len() - 1 {
    let shared_sender = sender.clone();
    thread::spawn(move || {
      shared_sender.send(values[i]).ok().expect("Unable to send");
    });
  }
}


fn read(reader: _Receiver) {
  loop {
    match reader.recv() {
      Ok(msg) => println!("Message is: {:?}", msg),
      Err(err) => {
        match err.cause() {
          Some(msg) => println!("Error is: {:?}", msg),
          _ => (),  // OK, no error, nothing more to read
        }
        break;
      }     
    }
  }
}

Thank you.


#2

Looks good. Instead of the loop over i in send_something you should probably loop over values.iter() directly.

And the type aliases with a leading underscore look weird. In these cases I prefer to do the following:

use std::sync::mpsc;
type Sender = mpsc::Sender<Sending>;
...

#3

This is what I did first:

fn send_something(sender: &_Sender) {
    let values = [12, 56, 5, 12];
    for value in values.iter() {
        let shared_sender = sender.clone();
        let temp_value = *value;
        thread::spawn(move || {
            shared_sender.send(temp_value).ok().expect("Unable to send");
        });
    }
}

But because *value comes values, I had this error when using *value without temp_value:

src/main.rs:51:16: 51:22 error: `values` does not live long enough
src/main.rs:51   for value in values.iter() {
                            ^~~~~~
note: in expansion of for loop expansion
src/main.rs:51:3: 56:4 note: expansion site
note: reference must be valid for the static lifetime...
src/main.rs:50:32: 57:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 50:31
src/main.rs:50   let values = [12, 56, 5, 12];
src/main.rs:51   for value in values.iter() {
src/main.rs:52     let shared_sender = sender.clone();
src/main.rs:53     thread::spawn(move || {
src/main.rs:54       shared_sender.send(*value).ok().expect("Unable to send");
src/main.rs:55     });

So I had to create a temp variable for the closure to copy from so the line:

        let temp_value = *value;

So it makes things complicated.

Thank you for the feedback.