I have a stuct that looks like this:
pub struct Coordinator {
map_tasks: Mutex<Vec<Task>>,
reduce_tasks: Mutex<Vec<Task>>,
}
And I have a function that is called with a parameter to determine which of the two vectors to modify. The function takes a type and an id to find in the vector and modify. My original approach is this:
impl Coordinator {
pub fn update_status(&self, task_type: TaskType, task_id: u8) {
if task_type == TaskType::Map {
let tasks = &mut self.map_tasks.lock().unwrap();
for task in tasks.iter_mut() {
if task.task_id == task_id {
task.status = TaskStatus::Success;
}
}
} else {
let tasks = &mut self.reduce_tasks.lock().unwrap();
for task in tasks.iter_mut() {
if task.task_id == task_id {
task.status = TaskStatus::Success;
}
}
}
}
}
I would like to shorten the code since a lot of it is duplicated. I've tried this, but it doesnt work with the error temporary value dropped while borrowed, consider using a "let" binding to create a longer lived value
impl Coordinator {
pub fn update_status(&self, task_type: TaskType, task_id: u8) {
let tasks;
if task_type == TaskType::Map {
tasks = &mut self.map_tasks.lock().unwrap();
} else {
tasks = &mut self.reduce_tasks.lock().unwrap();
}
for task in tasks.iter_mut() {
if task.task_id == task_id {
task.status = TaskStatus::Success;
}
}
}
}
How could I fix this?
You don't need to take a mutable reference into the guard, you can just store the guard directly. Also, if..else
is an expression, you can use it as a ternary:
impl Coordinator {
pub fn update_status(&self, task_type: TaskType, task_id: u8) {
let mut tasks = if task_type == TaskType::Map {
self.map_tasks.lock().unwrap()
} else {
self.reduce_tasks.lock().unwrap()
};
for task in tasks.iter_mut() {
if task.task_id == task_id {
task.status = TaskStatus::Success;
}
}
}
}