650 lines
20 KiB
Text
650 lines
20 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4e3ae322",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Multithreading in Rust"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "947ff014",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Managing Threads\n",
|
|
"\n",
|
|
"### Creating and joining threads\n",
|
|
"\n",
|
|
"* Creating a thread using `std::thread::spawn`\n",
|
|
"* Joining threads to wait for their completion using `join()`"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "e8d84fec",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Counting 1 in background ThreadId(2)\n",
|
|
"Counting 1 in spawned ThreadId(3)\n",
|
|
"Counting 2 in background ThreadId(2)\n",
|
|
"Counting 2 in spawned ThreadId(3)\n",
|
|
"Counting 3 in background ThreadId(2)\n",
|
|
"Counting 3 in spawned ThreadId(3)\n",
|
|
"Counting 4 in background ThreadId(2)\n",
|
|
"Counting 4 in spawned ThreadId(3)\n",
|
|
"Counting 5 in spawned ThreadId(3)\n",
|
|
"Counting 5 in background ThreadId(2)\n",
|
|
"Counting 6 in spawned ThreadId(3)\n",
|
|
"Counting 6 in background ThreadId(2)\n",
|
|
"Counting 7 in background ThreadId(2)\n",
|
|
"Counting 7 in spawned ThreadId(3)\n",
|
|
"Counting 8 in background ThreadId(2)\n",
|
|
"Counting 8 in spawned ThreadId(3)\n",
|
|
"Counting 9 in spawned ThreadId(3)\n",
|
|
"Counting 9 in background ThreadId(2)\n",
|
|
"Counting 10 in spawned ThreadId(3)\n",
|
|
"Counting 10 in background ThreadId(2)\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"use std::thread;\n",
|
|
"\n",
|
|
"fn background_counting() {\n",
|
|
" for i in 1..=10 {\n",
|
|
" println!(\"Counting {} in background {:?}\", i, thread::current().id());\n",
|
|
" thread::sleep(std::time::Duration::from_millis(50));\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"let thd_1 = thread::spawn(background_counting);\n",
|
|
"\n",
|
|
"let thd_2 = thread::spawn(|| {\n",
|
|
" for i in 1..=10 {\n",
|
|
" println!(\"Counting {} in spawned {:?}\", i, thread::current().id());\n",
|
|
" thread::sleep(std::time::Duration::from_millis(50));\n",
|
|
" }\n",
|
|
"});\n",
|
|
"\n",
|
|
"thd_1.join().unwrap();\n",
|
|
"thd_2.join().unwrap();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d64ca60d",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Sharing Data Between Threads\n",
|
|
"\n",
|
|
"\n",
|
|
"### Transfer Ownership\n",
|
|
"\n",
|
|
"* Safely transfer ownership of data to threads\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"id": "80c5a805",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Processing data_vec in thread ThreadId(4)\n",
|
|
"Sum of data_vec: 500500\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"()"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"let data_vec = (1..=1000).collect::<Vec<i32>>();\n",
|
|
"\n",
|
|
"let thd_process = thread::spawn(move || {\n",
|
|
" println!(\"Processing data_vec in thread {:?}\", thread::current().id());\n",
|
|
" thread::sleep(std::time::Duration::from_millis(500));\n",
|
|
" let sum: i32 = data_vec.iter().sum();\n",
|
|
" // panic!(\"Intentional panic after processing data_vec with sum {}\", sum);\n",
|
|
" sum\n",
|
|
"});\n",
|
|
"\n",
|
|
"match thd_process.join() {\n",
|
|
" Ok(sum) => println!(\"Sum of data_vec: {}\", sum),\n",
|
|
" Err(e) => println!(\"Thread panicked: {:?}\", e),\n",
|
|
"}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "72eaed46",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Shared Ownership - Immutable Data\n",
|
|
"\n",
|
|
"* Using `Arc<T>` for shared ownership across threads"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "01bd107d",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Min in thread ThreadId(6): 1\n",
|
|
"Max in thread ThreadId(6): 100\n",
|
|
"Sum in thread ThreadId(5): 5025\n",
|
|
"Final Results - Total Sum: 5025, Min: 1, Max: 100\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
":dep rand = \"0.9\"\n",
|
|
"\n",
|
|
"use rand::random_range;\n",
|
|
"use std::iter::from_fn;\n",
|
|
"use std::sync::Arc;\n",
|
|
"\n",
|
|
"let data: Vec<i32> = from_fn(|| Some(random_range(1..=100))).take(100).collect();\n",
|
|
"let shared_data = Arc::new(data);\n",
|
|
"\n",
|
|
"let thd_sum = {\n",
|
|
" let data_clone = Arc::clone(&shared_data);\n",
|
|
" thread::spawn(move || {\n",
|
|
" let sum: i32 = data_clone.iter().sum();\n",
|
|
" println!(\"Sum in thread {:?}: {}\", thread::current().id(), sum);\n",
|
|
" sum\n",
|
|
" })\n",
|
|
"}; \n",
|
|
"\n",
|
|
"let thd_max = {\n",
|
|
" let data_clone = Arc::clone(&shared_data);\n",
|
|
" thread::spawn(move || {\n",
|
|
" let min = data_clone.iter().min().cloned().unwrap();\n",
|
|
" println!(\"Min in thread {:?}: {}\", thread::current().id(), min);\n",
|
|
" let max = data_clone.iter().max().cloned().unwrap();\n",
|
|
" println!(\"Max in thread {:?}: {}\", thread::current().id(), max);\n",
|
|
" (min, max)\n",
|
|
" })\n",
|
|
"};\n",
|
|
"\n",
|
|
"let total_sum = thd_sum.join().unwrap();\n",
|
|
"let (min_value, max_value) = thd_max.join().unwrap();\n",
|
|
"\n",
|
|
"println!(\"Final Results - Total Sum: {}, Min: {}, Max: {}\", total_sum, min_value, max_value);"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "85f2b2a1",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Shared Mutable State Between Threads"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "3c499020",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"use std::sync::{Arc, Mutex};\n",
|
|
"\n",
|
|
"pub struct BankAccount {\n",
|
|
" // balance: f32\n",
|
|
" balance: Mutex<f32>,\n",
|
|
"}\n",
|
|
"\n",
|
|
"impl BankAccount {\n",
|
|
" pub fn new(initial_balance: f32) -> Self {\n",
|
|
" BankAccount { balance: Mutex::new(initial_balance) }\n",
|
|
" }\n",
|
|
" \n",
|
|
" pub fn deposit(&self, amount: f32) {\n",
|
|
" *self.balance.lock().unwrap() += amount;\n",
|
|
" }\n",
|
|
" \n",
|
|
" pub fn withdraw(&self, amount: f32) -> Result<(), String> {\n",
|
|
" let mut balance = self.balance.lock().unwrap();\n",
|
|
" if amount > *balance {\n",
|
|
" Err(\"Insufficient funds\".to_string())\n",
|
|
" } else {\n",
|
|
" *balance -= amount;\n",
|
|
" Ok(())\n",
|
|
" }\n",
|
|
" }\n",
|
|
"\n",
|
|
" fn transfer(&self, to: &BankAccount, amount: f32) -> Result<(), String> {\n",
|
|
" let mut from_balance = self.balance.lock().unwrap();\n",
|
|
" if amount > *from_balance {\n",
|
|
" return Err(\"Insufficient funds\".to_string());\n",
|
|
" }\n",
|
|
" let mut to_balance = to.balance.lock().unwrap();\n",
|
|
"\n",
|
|
" *from_balance -= amount;\n",
|
|
" *to_balance += amount;\n",
|
|
" \n",
|
|
" Ok(())\n",
|
|
" }\n",
|
|
" \n",
|
|
" pub fn balance(&self) -> f32 {\n",
|
|
" *self.balance.lock().unwrap()\n",
|
|
" }\n",
|
|
"}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "aa2240cd",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"fn pay_in(account: Arc<BankAccount>, amount: f32, count: usize) {\n",
|
|
" for _ in 0..count {\n",
|
|
" if account.balance() < 200.0 {\n",
|
|
" println!(\"Balance low: ${}, depositing ${}\", account.balance(), amount);\n",
|
|
" account.deposit(amount);\n",
|
|
" } \n",
|
|
"\n",
|
|
" std::thread::sleep(std::time::Duration::from_millis(10));\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"fn take_out(account: Arc<BankAccount>, amount: f32, count: usize) {\n",
|
|
" for _ in 0..count {\n",
|
|
" match account.withdraw(amount) {\n",
|
|
" Ok(_) => println!(\"Withdrew ${}, new balance: ${}\", amount, account.balance()),\n",
|
|
" Err(e) => println!(\"Failed to withdraw ${}: {}\", amount, e),\n",
|
|
" }\n",
|
|
"\n",
|
|
" std::thread::sleep(std::time::Duration::from_millis(20));\n",
|
|
" }\n",
|
|
"}"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "a22be054",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Withdrew $30, new balance: $70\n",
|
|
"Balance low: $70, depositing $50\n",
|
|
"Balance low: $120, depositing $50\n",
|
|
"Withdrew $30, new balance: $140\n",
|
|
"Balance low: $140, depositing $50\n",
|
|
"Balance low: $190, depositing $50\n",
|
|
"Withdrew $30, new balance: $210\n",
|
|
"Withdrew $30, new balance: $180\n",
|
|
"Balance low: $180, depositing $50\n",
|
|
"Withdrew $30, new balance: $200\n",
|
|
"Withdrew $30, new balance: $170\n",
|
|
"Withdrew $30, new balance: $140\n",
|
|
"Withdrew $30, new balance: $110\n",
|
|
"Withdrew $30, new balance: $80\n",
|
|
"Withdrew $30, new balance: $50\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"fn main() {\n",
|
|
" let mut account = Arc::new(BankAccount::new(100.0));\n",
|
|
"\n",
|
|
" let mut account_for_pay_in = Arc::clone(&account);\n",
|
|
" let pay_in_thread = std::thread::spawn(move || pay_in(account_for_pay_in, 50.0, 10));\n",
|
|
"\n",
|
|
" let mut account_for_take_out = Arc::clone(&account);\n",
|
|
" let take_out_thread = std::thread::spawn(move || take_out(account_for_take_out, 30.0, 10));\n",
|
|
"\n",
|
|
" pay_in_thread.join().unwrap();\n",
|
|
" take_out_thread.join().unwrap();\n",
|
|
"}\n",
|
|
"\n",
|
|
"main();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7f7968af",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Send and Sync"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e02fb112",
|
|
"metadata": {},
|
|
"source": [
|
|
"* The `Send` and `Sync` traits affect the ability to transfer and share data between threads\n",
|
|
"* Types that implement `Send` can be transferred to another thread\n",
|
|
" * Most primitive types in Rust implement `Send`\n",
|
|
" * Owned types like `String` and `Vec<T>` also implement `Send`\n",
|
|
" * Types that do not implement `Send` include raw pointers and types that manage non-thread-safe resources: `Rc<T>`, `RefCell<T>`\n",
|
|
"* Types that implement `Sync` can be referenced from multiple threads safely\n",
|
|
" * Immutable references (`&T`) are `Sync` if `T` is `Sync`\n",
|
|
" * Mutable references (`&mut T`) are not `Sync`\n",
|
|
" * Types that do not implement `Sync` include `Cell<T>` and `RefCell<T>`\n",
|
|
" * Types like `Mutex<T>` and `RwLock<T>` provide safe shared mutable access across threads"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7c6393dc",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Deadlocks"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "5ae7b3aa",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $450, to $350\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $320, to $480\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $290, to $510\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $460, to $340\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $310, to $490\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $440, to $360\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $330, to $470\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $420, to $380\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $350, to $450\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $400, to $400\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $370, to $430\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $380, to $420\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $390, to $410\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $360, to $440\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $410, to $390\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $340, to $460\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $430, to $370\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $320, to $480\n",
|
|
"Transferred $30 from BankAccount#2 to BankAccount#1. New balances: from $450, to $350\n",
|
|
"Transferred $50 from BankAccount#1 to BankAccount#2. New balances: from $300, to $500\n",
|
|
"Final Balance of Account A: $300\n",
|
|
"Final Balance of Account B: $500\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"use std::sync::{Arc, Mutex};\n",
|
|
"\n",
|
|
"mod Bank {\n",
|
|
" use std::sync::{Arc, Mutex};\n",
|
|
"\n",
|
|
" pub struct BankAccount {\n",
|
|
" id: u32,\n",
|
|
" balance: Mutex<f32>,\n",
|
|
" }\n",
|
|
"\n",
|
|
" impl BankAccount {\n",
|
|
" pub fn new(id: u32, initial_balance: f32) -> Self {\n",
|
|
" BankAccount { id, balance: std::sync::Mutex::new(initial_balance) }\n",
|
|
" }\n",
|
|
"\n",
|
|
" pub fn transfer(&self, to: &BankAccount, amount: f32) -> Result<(), String> {\n",
|
|
"\n",
|
|
" let (mut from_balance, mut to_balance) = if self.id < to.id {\n",
|
|
" let from_balance = self.balance.lock().unwrap();\n",
|
|
" let to_balance = to.balance.lock().unwrap();\n",
|
|
" (from_balance, to_balance)\n",
|
|
" } else {\n",
|
|
" let to_balance = to.balance.lock().unwrap();\n",
|
|
" let from_balance = self.balance.lock().unwrap();\n",
|
|
" (from_balance, to_balance)\n",
|
|
" };\n",
|
|
"\n",
|
|
" //let mut from_balance = self.balance.lock().unwrap();\n",
|
|
" //let mut to_balance = to.balance.lock().unwrap();\n",
|
|
"\n",
|
|
" *from_balance -= amount;\n",
|
|
" *to_balance += amount;\n",
|
|
" \n",
|
|
" Ok(())\n",
|
|
" }\n",
|
|
" \n",
|
|
" pub fn balance(&self) -> f32 {\n",
|
|
" *self.balance.lock().unwrap()\n",
|
|
" }\n",
|
|
"\n",
|
|
" pub fn id(&self) -> u32 {\n",
|
|
" self.id\n",
|
|
" }\n",
|
|
" }\n",
|
|
"\n",
|
|
" pub fn transfer_funds(from: Arc<BankAccount>, to: Arc<BankAccount>, amount: f32, count: usize) {\n",
|
|
" for _ in 0..count {\n",
|
|
" match from.transfer(&to, amount) {\n",
|
|
" Ok(_) => println!(\"Transferred ${} from BankAccount#{} to BankAccount#{}. New balances: from ${}, to ${}\", \n",
|
|
" amount, from.id(), to.id(), from.balance(), to.balance()),\n",
|
|
" Err(e) => println!(\"Failed to transfer ${} from BankAccount#{} to BankAccount#{}: {}\", \n",
|
|
" amount, from.id(), to.id(), e),\n",
|
|
" }\n",
|
|
"\n",
|
|
" std::thread::sleep(std::time::Duration::from_millis(15));\n",
|
|
" }\n",
|
|
" }\n",
|
|
"\n",
|
|
"}\n",
|
|
"\n",
|
|
"fn main() {\n",
|
|
" let account_a = Arc::new(Bank::BankAccount::new(1, 500.0));\n",
|
|
" let account_b = Arc::new(Bank::BankAccount::new(2, 300.0));\n",
|
|
"\n",
|
|
" let account_a_for_transfer_1 = Arc::clone(&account_a);\n",
|
|
" let account_b_for_transfer_1 = Arc::clone(&account_b);\n",
|
|
"\n",
|
|
" let thd_transfer_from_a_to_b = std::thread::spawn(move || {\n",
|
|
" Bank::transfer_funds(account_a_for_transfer_1, account_b_for_transfer_1, 50.0, 10);\n",
|
|
" });\n",
|
|
"\n",
|
|
" let account_a_for_transfer_2 = Arc::clone(&account_a);\n",
|
|
" let account_b_for_transfe_2 = Arc::clone(&account_b);\n",
|
|
" let thd_transfer_from_b_to_a = std::thread::spawn(move || {\n",
|
|
" Bank::transfer_funds(account_b_for_transfe_2, account_a_for_transfer_2, 30.0, 10);\n",
|
|
" });\n",
|
|
"\n",
|
|
" thd_transfer_from_a_to_b.join().unwrap();\n",
|
|
"\n",
|
|
" println!(\"Final Balance of Account A: ${}\", account_a.balance());\n",
|
|
" println!(\"Final Balance of Account B: ${}\", account_b.balance());\n",
|
|
"}\n",
|
|
"\n",
|
|
"main();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "52220484",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Thread Communication With Channels"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b3653ab8",
|
|
"metadata": {},
|
|
"source": [
|
|
"* Using channels (`std::sync::mpsc`) for thread communication simplifies data transfer between threads\n",
|
|
"* Channels provide a way to send data from one thread to another safely\n",
|
|
" * Create a channel with `mpsc::channel()` - returns a sender and a receiver\n",
|
|
" * Send data between threads using the `send()` method on the sender\n",
|
|
" * Receive data in the main thread using the `recv()` method or iterating over the receiver"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"id": "de2665bc",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Received: Hello from the sender thread\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"use std::thread;\n",
|
|
"use std::sync::mpsc;\n",
|
|
"\n",
|
|
"fn main() {\n",
|
|
" let (sender, receiver) = mpsc::channel();\n",
|
|
"\n",
|
|
" let sender_clone = sender.clone();\n",
|
|
" let thd_sender = thread::spawn(move || {\n",
|
|
" let message = \"Hello from the sender thread\".to_string();\n",
|
|
" sender_clone.send(message).unwrap();\n",
|
|
" });\n",
|
|
"\n",
|
|
" let received_data = receiver.recv().unwrap();\n",
|
|
" println!(\"Received: {}\", received_data);\n",
|
|
"\n",
|
|
" thd_sender.join().unwrap();\n",
|
|
"}\n",
|
|
"\n",
|
|
"main();"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "74bd9f3b",
|
|
"metadata": {},
|
|
"source": [
|
|
"### Message Passing with Structs"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"id": "73c689b8",
|
|
"metadata": {
|
|
"vscode": {
|
|
"languageId": "rust"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Received Message - ID: 42, Content: Important data\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"use std::thread;\n",
|
|
"use std::sync::mpsc;\n",
|
|
"\n",
|
|
"struct CustomMessage {\n",
|
|
" id: u32,\n",
|
|
" content: String,\n",
|
|
"}\n",
|
|
"\n",
|
|
"fn main() {\n",
|
|
" let (sender, receiver) = mpsc::channel();\n",
|
|
"\n",
|
|
" let sender_clone = sender.clone();\n",
|
|
" let handle = thread::spawn(move || {\n",
|
|
" let message = CustomMessage {\n",
|
|
" id: 42,\n",
|
|
" content: \"Important data\".to_string(),\n",
|
|
" };\n",
|
|
" sender_clone.send(message).unwrap();\n",
|
|
" });\n",
|
|
"\n",
|
|
" let received_message = receiver.recv().unwrap();\n",
|
|
" println!(\"Received Message - ID: {}, Content: {}\", received_message.id, received_message.content);\n",
|
|
"\n",
|
|
" handle.join().unwrap();\n",
|
|
"}\n",
|
|
"\n",
|
|
"main();"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Rust",
|
|
"language": "rust",
|
|
"name": "rust"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": "rust",
|
|
"file_extension": ".rs",
|
|
"mimetype": "text/rust",
|
|
"name": "Rust",
|
|
"pygment_lexer": "rust",
|
|
"version": ""
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|