Day 4 Morning Exercise

Dining Philosophers

(back to exercise)

  1. // Copyright 2022 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ANCHOR: Philosopher
  15. use std::sync::mpsc;
  16. use std::sync::{Arc, Mutex};
  17. use std::thread;
  18. use std::time::Duration;
  19. struct Fork;
  20. struct Philosopher {
  21. name: String,
  22. // ANCHOR_END: Philosopher
  23. left_fork: Arc<Mutex<Fork>>,
  24. right_fork: Arc<Mutex<Fork>>,
  25. thoughts: mpsc::SyncSender<String>,
  26. }
  27. // ANCHOR: Philosopher-think
  28. impl Philosopher {
  29. fn think(&self) {
  30. self.thoughts
  31. .send(format!("Eureka! {} has a new idea!", &self.name))
  32. .unwrap();
  33. }
  34. // ANCHOR_END: Philosopher-think
  35. // ANCHOR: Philosopher-eat
  36. fn eat(&self) {
  37. // ANCHOR_END: Philosopher-eat
  38. println!("{} is trying to eat", &self.name);
  39. let left = self.left_fork.lock().unwrap();
  40. let right = self.right_fork.lock().unwrap();
  41. // ANCHOR: Philosopher-eat-end
  42. println!("{} is eating...", &self.name);
  43. thread::sleep(Duration::from_millis(10));
  44. }
  45. }
  46. static PHILOSOPHERS: &[&str] =
  47. &["Socrates", "Plato", "Aristotle", "Thales", "Pythagoras"];
  48. fn main() {
  49. // ANCHOR_END: Philosopher-eat-end
  50. let (tx, rx) = mpsc::sync_channel(10);
  51. let forks = (0..PHILOSOPHERS.len())
  52. .map(|_| Arc::new(Mutex::new(Fork)))
  53. .collect::<Vec<_>>();
  54. for i in 0..forks.len() {
  55. let tx = tx.clone();
  56. let mut left_fork = forks[i].clone();
  57. let mut right_fork = forks[(i + 1) % forks.len()].clone();
  58. // To avoid a deadlock, we have to break the symmetry
  59. // somewhere. This will swap the forks without deinitializing
  60. // either of them.
  61. if i == forks.len() - 1 {
  62. std::mem::swap(&mut left_fork, &mut right_fork);
  63. }
  64. let philosopher = Philosopher {
  65. name: PHILOSOPHERS[i].to_string(),
  66. thoughts: tx,
  67. left_fork,
  68. right_fork,
  69. };
  70. thread::spawn(move || {
  71. for _ in 0..100 {
  72. philosopher.eat();
  73. philosopher.think();
  74. }
  75. });
  76. }
  77. drop(tx);
  78. for thought in rx {
  79. println!("{thought}");
  80. }
  81. }