I tried to solve The Dining Philosophers Problem using mutex, arc, condvar. does this satasfies the solution?
use std::sync::{Arc, Condvar, Mutex};
use std::thread;
struct ResourcePool {
resources: Mutex<Vec<bool>>,
available: Condvar,
}
impl ResourcePool {
fn new(size: usize) -> ResourcePool {
ResourcePool {
resources: Mutex::new(vec![true; size]),
available: Condvar::new(),
}
}
fn acquire(&self) -> Vec<usize> {
let mut resourses = self.resources.lock().unwrap();
loop {
if let Some(index) = find_available_resources(&resourses, 1) {
mark_resourcs_as_unavailable(&mut resourses, &index);
return index;
}
resourses = self.available.wait(resourses).unwrap();
}
}
fn release(&self, index: Vec<usize>) {
let mut resources = self.resources.lock().unwrap();
for i in index {
resources[i] = true;
}
self.available.notify_all();
}
}
fn find_available_resources(resources: &Vec<bool>, count: usize) -> Option<Vec<usize>> {
let mut index = Vec::new();
// println!("resources ???? {:?}", resources);
for i in 0..resources.len() {
if resources[i] {
// println!("free = {}", i);
index.push(i);
if index.len() == count {
return Some(index);
}
}
}
None
}
fn mark_resourcs_as_unavailable(resources: &mut Vec<bool>, index: &Vec<usize>) {
for i in index {
resources[*i] = false;
}
}
pub fn main() {
let pool = Arc::new(ResourcePool::new(5));
let mut handles = vec![];
for i in 0..5 {
let pool = Arc::clone(&pool);
let handle = thread::spawn(move || {
let index = pool.acquire();
let index2 = pool.acquire();
println!("thread {} acquired resources {:?} {:?}", i, index, index2);
thread::sleep(std::time::Duration::from_secs(2));
pool.release(index.clone());
pool.release(index2.clone());
println!("thread {} released resource {:?} {:?}", i, index, index2);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
}