Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mutexes and lambda functions in c++

When dealing with concurrency problems I often use std::unique_lock<std::mutex> and std::lock_guard<std::mutex>, no problem with both.

I also extended std::mutex to be able to use it as follow:

mutex.protect([](){
    // my protected code here
}) ;

It locks the mutex and releases it around the lambda call.

Is such a similar behavior already implemented inside boost or the standard library?

like image 275
Falco Avatar asked Jan 21 '16 12:01

Falco


People also ask

What is a lambda function in C?

Lambda Function − Lambda are functions is an inline function that doesn't require any implementation outside the scope of the main program. Lambda Functions can also be used as a value by the variable to store. Lambda can be referred to as an object that can be called by the function (called functors).

What is a mutex in C?

(since C++11) The mutex class is a synchronization primitive that can be used to protect shared data from being simultaneously accessed by multiple threads.

What is the difference between Unique_lock and Lock_guard?

A lock_guard always holds a lock from its construction to its destruction. A unique_lock can be created without immediately locking, can unlock at any point in its existence, and can transfer ownership of the lock from one instance to another.

What do mutexes do?

In computer programming, a mutex (mutual exclusion object) is a program object that is created so that multiple program thread can take turns sharing the same resource, such as access to a file.


2 Answers

Boost Thread has this: http://www.boost.org/doc/libs/1_58_0/doc/html/thread/synchronization.html#thread.synchronization.with_lock_guard

You can use it like you'd expect:

std::mutex mx;

boost::with_lock_guard(mx, []{
    // protected stuff
});

It even supports the usual INVOKE semantics:

int foo(int,double) { return 42; }

// ...

int answer = boost::with_lock_guard(mx, foo, 3, 3.14);

Manual Standard Library Only implementation

You can easily add a thing like this yourself:

template <typename M, typename F, typename... Args> 
    auto my_with_lock_guard(M& mx, F&& f, Args&&... args) {
        std::lock_guard<M> lk(mx);
        return std::forward<F>(f)(std::forward<Args>(args)...);
    }

If the standard ever adopts a proposal like this you can easily swap it out.

like image 84
sehe Avatar answered Oct 19 '22 08:10

sehe


If all you want to do is protect code in a smaller scope inside a function you don't need to extend mutex by writing your own protect function. You can just do as below, use curly braces to create a local scope, and when the scope is exited the mutex will automatically be unlocked in an exception safe way.

double process_func() { 
// do some stuff
    { //start a new scope block
      std::lock_guard<my_mutex> g; // mutex is locked here.
      []() { } // your lambda that needs to be protected
    } // Mutex is released here.
// do more stuff
} 

Of course this has the disadvantage over your custom function that, it is difficult to maintain. Someone can come later and inject more code without knowing what they are doing.

like image 26
BGR Avatar answered Oct 19 '22 08:10

BGR