Local static variable shared between all instances of a generic lambda expression

I have code in which a non-generic lamba expression has a local static variable: a mutex for a critical section. Something to simplify:

int i = 0; auto lambda = [&i](int &v) { static std::mutex mutex; std::lock_guard<std::mutex> lock(mutex); /* critical section with v and i */}; } 

Now the critical section implemented in this lambda expression can be reused verbatim for types other than int & , and I would like the change as easy as replacing int with auto in the declarator, for example:

 auto lambda = [&i](auto &v) 

Unfortunately, if I do this, lambda(int&) and lambda(float&) will no longer use the same local static variable, which will defeat locking in the critical section.

What will be the simplest code change that meets all these requirements:

  • provide the community I need; and
  • make sure that I have one mutex that is common to all instances of the critical section; and
  • does not display the mutex in a public form

The solution that will work is to replace the lambda expression with a class using the template method, something like this:

 class Lambda { public: Lambda(int &i) : i_(i) {} template<class V> void operator()(V &v) { std::lock_guard<std::mutex> lock(mutex_); /* critical section with v and i_ */ }; private: static std::mutex mutex_; int &i_; }; std::mutex Lambda::mutex_; int i = 0; Lambda lambda(i); 

This will work (with reservations, like a private link i_ ), but it looks very cumbersome compared to the original lambda expression. Will there be anything more straightforward?

+5
source share
1 answer

You can init-capture shared_ptr, which will look like it is defined as a member variable of the closure type, and therefore all copies of the closure object will have the same mutex:

  auto lambda = [&i, m = std::make_shared<std::mutex>()](auto &v) { std::lock_guard<std::mutex> lock(*m); /* critical section with v and i */ }; 
+5
source

Source: https://habr.com/ru/post/1247079/


All Articles