Standard Mutex is released once out of scope

C++ Implementation:


//growing phase
    for (int index : sorted_transaction) {
      Row &row = table[index];
      row.lock.lock();
    }
//critical section
    for (int index : random_transaction) {
      Row &row = table[index];
      int row_data = row.getData();
      row_data += 1;
      row.setData(row_data);
    }
//shrinking phase
    for (int index : sorted_transaction) {
      Row &row = table[index];
      row.lock.unlock();
    }

Rust Attempt

        let mut acquired_locks: Vec<&MutexGuard<i32>> = Vec::new();
//        sort phase
        sorted_readset.rdxsort();

//      growing phase
        for index in sorted_readset {
            let u_index = index  as usize;
            let row = &table[u_index];
            let guard = row.lock.lock().unwrap();
            acquired_locks.push(&guard);
        }
//critical section
        for index in random_readset {
            let u_index = index as usize;
            let mut row = &mut table[u_index];
            row.value = row.value + 1;
        }

//since this will become out of scope, it'll automatically shrink

As you can see, it's impossible since the Mutex is immediately released after exiting the loop, once ownership is released. I attempted to transfer ownership by appending it to a vector. That throws an error since the lockguard is a borrowed value.

You should iterate the Mutexes by reference, and hold the MutexGuards by value. Your actual mutations should also happen through the guards, because unlike C++, Mutex directly wraps its protected values.

3 Likes

As an aid to future seaches on this and related topics, would you consider revising the title of this thread from its current definitive-but-incorrect statement to something like "Help implementing 2-phase locking in Rust". As you can see from @cuviper's response, it is not impossible to implement 2-phase locking in Rust; it's just that the approach differs from that in C++.

1 Like

You should be able to put the guard into a vector, but the vector must take ownership by having the type Vec<MutexGuard<i32>> since otherwise the guard is dropped at the end of the body of the for loop, invalidating the reference to it you put in the vector.

1 Like

If you want more C++ style locks, you can use parking_lot's RawMutex.

Thanks for the feedback!

1 Like

Thanks everyone. Actually just new to Rust. So, I solved the problem of storing the MutexGuards. I'm running into a different problem hehehehehe should be a different thread. Thanks for all your help :slight_smile:

I can't iterate through the mutexes by references since I need to modify them during the critical phase... Keeping hold of the mutexes as mutable references in a loop throws an error.

Solved the problem by enclosing the value with a mutex and updating the value inside a mutex. Thanks everyone.

1 Like

Mutex is explicitly designed so that, given the &Mutex, you can modify the underlying value by acquiring MutexGuard.