Try_lock with a vector

Hi guys, I started studying rust 2 weeks ago to do an easy project for an exam of concurrent and parallel programming.

I have a vector of Mutexes that contain a struct Node, implemented in the following code.
Then I create another vector where i put all the cloned elements of the previous vector.
Since I have two threads I would like to check if an element of the cloned vector is available, if it is, I want to lock it, otherwise I want to take another element of the cloned vector.
To do that I generate a random number n and I try to lock the cloned_vector[n] cell: if it fails I go to the next cycle of the loop, if it succeeds I lock it.

Now, according to the guide (here), if I want to use try_lock on an element of the cloned vector I should do something like this

use std::sync::{Arc, Mutex}; 
use std::thread;
let mutex = Arc::new(Mutex::new(0)); 
let c_mutex = mutex.clone
thread::spawn(move || {
    let mut lock = c_mutex.try_lock();
    if let Ok(ref mut mutex) = lock {
        **mutex = 10;
    } else {
        println!("try_lock failed");
    }
}).join().expect("thread::spawn failed");
assert_eq!(*mutex.lock().unwrap(), 10);

I tried to replicate the pattern but I obtain an error at compile time which I report after the code.

extern crate rand;
use std::sync::{Mutex, Arc};
use std::thread;
use rand::Rng;

#[derive(Copy, Clone)] 
struct Node {
    colour: (i32, bool),
    forbidden: [bool; 3],
}

fn main() {

    //vector of mutex node
    let mut nodes = vec![];
    for _ in 0..20 {
        nodes.push(Arc::new(Mutex::new(Node{colour: (0, false), forbidden: [true; 3]})));
    } 

    //threads vector
    let mut handles = vec![];

    for _ in 0..2 {
    
        //here i clone the vector of nodes
        let mut cloned_nodes = vec![];
        for i in 0..20 {
            cloned_nodes.push(Arc::clone(&nodes[i]));
        }        

        let handle = thread::spawn( move || {
            loop {

                let n = rand::thread_rng().gen_range(0, 20);
                
                let m = n as usize;
                let mut lock = cloned_nodes[m].try_lock();
                if let Ok(ref mut nodes[m]) = lock 
                else { continue; }
	
            }
        });

        handles.push(handle);

    }  

    for handle in handles {
        handle.join().unwrap();
    }                              
}

The error is

error: expected one of `)`, `,`, `@`, or `|`, found `[`
   --> src/main.rs:126:26
    |
126 |         if let Ok(ref mut nodes[m]) = lock 
    |                                ^ expected one of `)`, `,`, `@`, or `|` here

error: missing condition for `if` expression
   --> src/main.rs:126:5
    |
126 |         if let Ok(ref mut nodes[m]) = lock 
    |           ^ expected if condition here

After two days of attempts I gave up. I know that the code isn't well written but I have only 2 weeks to learn the language and to hand in the project.
You're my last hope guys! Thanks for the attention!

The if let expression defines a new variable, and you can't use [m] in a variable name.

Any suggestion? How can a thread take possession of a mutex inside a vector?

What do you mean by "take possession"? You need to give some more information on what you're trying to do with the locks here before we can help you. The usual pattern is to use the lock to do something with the value in the mutex and then release it. That doesn't normally involve moving the mutex or storing the lock.

You probably want something like

if let Ok(item) = cloned_nodes[m].try_lock() {
    // use item here
} else {
    // failed to lock
}
2 Likes

It works! What a community!
You're awesome!

2 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.