Bind mutex to object Bind mutex to object multithreading multithreading

Bind mutex to object


If you wish to achieve that the std::mutex will only be held until an operation is performed on the protected object, you can write a wrapper class as follows:

#include <cstdio>#include <mutex>template<typename T>class LockAssignable {public:    LockAssignable& operator=(const T& t) {        std::lock_guard<std::mutex> lk(m_mutex);        m_protected = t;        return *this;    }    operator T() const {        std::lock_guard<std::mutex> lk(m_mutex);        return m_protected;    }        /* other stuff */private:    mutable std::mutex m_mutex;    T m_protected {};};inline int factorial(int n) {    return (n > 1 ? n * factorial(n - 1) : 1);}int main() {    int var = 5;    LockAssignable<int> mvar;    mvar = factorial(var);    printf("Result: %d\n", static_cast<int>(mvar));    return 0;}

In the example above the factorial will be calculated in advance and the m_mutex will be acquired only when the assignment or the implicit conversion operator being called on mvar.

Assembly Output


For the primitive data types you can use std::atomic with std::memory_order_relaxed.The documentation states that:

there are no synchronization or ordering constraints imposed on other reads or writes, only this operation's atomicity is guaranteed

In the following example, the atomicity of the assignation is guaranteed, but the compiler should be able to move the operations.

std::atomic<int> z = {0};int a = 3;z.store(a*a, std::memory_order_relaxed);

For objects, I thought of several solutions, but:

  • There is no standard way to remove ordering requirements from std::mutex.
  • It is not possible to create a std::atomic<std::vector>.
  • It is not possible to create a spinlock using std::memory_order_relaxed (see the example).

I have found some answers that state that:

  • If the function is not visible in the compilation unit, the compiler generates a barrier because it does not know which variables it uses.
  • If the function is visible and there is a mutex, the compiler generates a barrier.For example, see this and this

So, in order to express that mvar_mutex is bound to the variable, you can use some classes as stated by the other answers but I do not think it is possible to fully allow the reordering of the code.


I want to express that mvar_mutex is bound to the variable mvar and protects only that variable.

You can't do this. A mutex actually guards the critical region of machine instructons between the acquisition and release. Only by convention is that associated with a particular instance of shared data.

To avoid doing unnecessary steps inside the critical region, keep the critical regions as simple as possible. In a critical region, only with local variables which the compiler can "see" are obviously not shared with other threads, and with one set of shared data belonging to that mutex. Try not to access other data in the critical region that might be suspected of being shared.

If you could have your proposed language feature, it would only introduce the possibility of error into a program. All it does is take code which is now correct, and make some of it incorrect (in exchange for the promise of some speed: that some code stays correct and is faster, because extraneous computations are moved out of the critical region).

It's like taking a language which already has a nice order of evaluation, in which a[i] = i++ is well defined, and screwing it up with unspecified evaluation order.