w3resource

Implementing a Message Broadcast System in Rust

Rust Error Propagation: Exercise-7 with Solution

Write a Rust program to implement a message broadcast system using channels. Create one sender thread and multiple receiver threads. When the sender sends a message through the channel, all receiver threads should receive and print the message.

Sample Solution:

Rust Code:

use std::sync::{mpsc, Arc, Mutex}; // Import necessary modules for multi-threading
use std::thread; // Import necessary module for multi-threading

const NUM_RECEIVERS: usize = 3; // Define the number of receiver threads
const MESSAGE: &str = "Hello, world!"; // Define the message to be sent

fn main() {
    // Create a channel for communication
    let (sender, receiver) = mpsc::channel();

    // Create an Arc to share ownership of the receiver across threads
    let receiver = Arc::new(Mutex::new(receiver));

    // Spawn receiver threads
    let mut handles = Vec::new(); // Create a vector to store thread handles
    for _ in 0..NUM_RECEIVERS {
        let rx = Arc::clone(&receiver); // Clone the Arc to pass to each receiver thread
        let handle = thread::spawn(move || { // Spawn a new receiver thread
            // Receive and print messages
            loop {
                match rx.lock().unwrap().recv() { // Lock the mutex and receive messages from the channel
                    Ok(msg) => println!("Received message: {}", msg), // If message received successfully, print it
                    Err(_) => break, // Break the loop if the channel is closed
                }
            }
        });
        handles.push(handle); // Store the handle of the spawned thread
    }

    // Spawn sender thread
    let sender_handle = thread::spawn(move || {
        // Send message to all receivers
        for _ in 0..NUM_RECEIVERS {
            sender.send(String::from(MESSAGE)).unwrap(); // Send the message through the channel
        }
        drop(sender); // Close the channel after sending all messages
    });

    // Wait for sender and receiver threads to finish
    sender_handle.join().unwrap(); // Wait for the sender thread to finish
    for handle in handles {
        handle.join().unwrap(); // Wait for each receiver thread to finish
    }
}

Output:

Received message: Hello, world!
Received message: Hello, world!
Received message: Hello, world!

Explanation:

In the exercise above,

  • Import modules: The code imports modules for multi-threading (std::sync::mpsc for channels and std::thread for thread management).
  • Define constants: It defines the constants 'NUM_RECEIVERS' and 'MESSAGE'. 'NUM_RECEIVERS' specifies the number of receiver threads to spawn, and 'MESSAGE' contains the message to be sent.
  • Main function:
    • Channel creation: It creates a channel for communication between sender and receiver threads.
    • Shared receiver: It wraps the receiver in an 'Arc' and 'Mutex' to allow safe sharing among multiple threads.
    • Spawn receiver threads: It spawns multiple receiver threads. Each thread locks the mutex, receives messages from the channel, and prints them until the channel is closed.
    • Spawn sender thread: It spawns a sender thread that sends the message to all receiver threads through the channel.
    • Wait for threads to finish: It waits for both sender and receiver threads to finish execution using "join()".
  • Sender thread: Sends the message to all receivers through the channel.
  • Receiver threads: Receive messages from the channel, print them, and break the loop if the channel is closed.

Rust Code Editor:

Previous: Implementing Synchronous Channels in Rust.
Next: Demonstrating Buffered Channels in Rust.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.