How channel receiver block current thread?

Hi, in this example:

can anyone explain to me why "after receiving all threads" printed earlier than "thread 2 finished"
I suppose the receiver should block the current thread until all threads have been completed.
but it seems the join command has blocked the current thread

Because "after receiving all threads" should really be "after receiving all the messages from all the senders". The receiver doesn't block until the thread completes, that's the job of the "join" function. The receiver, in your case, blocks until the first message arrives. And naturally, once both threads are finished (as confirmed by your "thread # finished"), the "join" completes and "after joining all" is shown.

By the way, you can paste your code in here by simply wrapping it in three backticks (```) - no copy/pasting of any code screenshots necessary. Although I personally don't hate it, many people here read new posts on their phones, and reading such a screen there would be quite a pain.

2 Likes

If I add this sentence:

println!("what is inside ids: {:?}", ids)

after

ids.push(rx.recv());

the actual code snippet should be:

for _ in 0..NTHREADS {
        // The `recv` method picks a message from the channel
        // `recv` will block the current thread if there are no messages available
        ids.push(rx.recv());
        println!("what is inside ids: {:?}", ids)
    }

the output became:

thread 0 finished
what is inside ids: [Ok(0)]
what is inside ids: [Ok(0), Ok(1)]
what is inside ids: [Ok(0), Ok(1), Ok(2)]
thread 1 finished
thread 2 finished
[Ok(0), Ok(1), Ok(2)]

How do I have access to the actual values before threads have been finished?
I mean, we have a place we should fill it, but by what? rx.recv() supposed to return a value immediately after push called. What is this result? The println shows that we have a result, but our thread has not been done yet.
Can you explain the order of running this code? I can't get it. I'm really confused.

Not after, but before, since it's an argument to push. And it will wait until tx.send executes, to return whatever was passed to send.

Well, send is not the last instruction in the thread, so the value will be here while thread is still alive.

1 Like

Not quite sure what you meant here - which "actual" values do you want to get access to? You've spawned several threads, passing a Sender<i32> to each of them, and each of them sends their id to your Receiver<i32>, which gets it and push-es it into your ids vector as a Result. What do you need?

Not sure what you meant here either, in all honesty.

Not quite true, as @Cerber-Ursi pointed out - ids.push(rx.recv()) means "get whatever value the rx.recv() returns and then call ids.push(...) with it. It's a simple function chain, same as:

let received = rx.recv();
ids.push(received);

Have you read the book yet?

You have a Result, which is used as a wrapper for the returned value from a function which may fail, which is what your recv() function returns when you call it. It returns a Result<i32> instead of a regular i32 because it may happen that you try to recv values which are no longer being sent to you (for instance, when all of your Sender<i32> have done their job and got dropped once the threads have finished their work), there might be nothing there to receive. If you want to get the actual value inside your Result-s, you can do something like this:

while let Ok(integer) = rx.recv() {
  println!("received: {}", integer);
}

Here we're blocking thread, waiting for the next value to arrive, printing it, until the first error.

I could, but I get the feeling that you haven't gone through the basics yet - start with the book (which I linked to earlier), go through it bit by bit, making sure not to skip any parts you find confusing, and by the end most things should become much less over your head. Naturally, ask here if you get stuck - but asking people to explain the same concepts which were outlined in what is de-facto an official guide for Rust, used by countless people as a reference, is just a little bit too much.

1 Like

I apologize, my bad.
I was just confused about how channels work. Now I realized what happens in this code exactly.
I read the book twice, and I already finished rust-by-example. English is not my native language, and I think I couldn't ask my question as precisely as what is in my mind.

No worries - and I'm glad I could help.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.