this post was submitted on 06 Jul 2023
13 points (100.0% liked)

C++

1783 readers
1 users here now

The center for all discussion and news regarding C++.

Rules

founded 1 year ago
MODERATORS
 

I want to free my code from the 5 std::mutex::unlock calls per function in favor of std::lock_guard. But I have the problem, that I have to keep the mutex locked when entering asynchronous callbacks.

Take this code for example:

std::map<std::size_t, std::set<std::size_t>> my_map;

size_t bar1 = ...;
size_t bar2 = ...;

std::lock_guard guard(my_map); // lock the map
my_map[p].insert(10);
foo(bar1, [&my_map](const auto& p){
    my_map[p].insert(10);

    // here we can unlock
});

foo is computing sth and then asynchronously calling the given lambda function and passing a parameter e to it. I need my_map to be locked the whole time. Keep in mind, that this is just an code example which might not map the real problem, so please don't optimize my given code.

you are viewing a single comment's thread
view the rest of the comments
[–] corristo 6 points 1 year ago* (last edited 1 year ago)

std::lock_guard and it's superior alternative std::scoped_lock both deliberately cannot be moved, so you won't be able to make it work with these types. But, assuming foo will cause the lambda to be destroyed once it is done executing you can use the more flexible std::unique_lock and move that into the lambda:

std::unique_lock lock(my_map);
my_map[p].insert(10);
foo(bar1, [&my_map, l = std::move(lock)] (const auto& p) {
      my_map[p].insert(10);
});

If the lambda does not capture anything whose destructor could call code that tries to lock this same mutex by value and foo destroys the lambda immediately after the lambda has finished executing then this does exactly what you want.