Access to a tuple of tuples of pointers and mutexes with a stream

Given std::tuple ,

 using Tuple1 = std::tuple<Foo1*, Bar1*, std::shared_ptr<std::mutex>>; using Tuple2 = std::tuple<Foo2*, Bar2*, std::shared_ptr<std::mutex>>; std::tuple<Tuple1, Tuple2> tuple; 

And the function

 void baz() { auto tup = std::get<0>(tuple); std::lock_guard<std::mutex> lk(*std::get<2>(tup)); // Do something with std::get<0>(tup) and std::get<1>(tup) } 

Accordingly , the issue of SO accessing std::tuple not essentially thread safe, but what about example code? Is it possible that undefined / strange things will happen?

It is assumed that FooN and BarN are only available after locking.

+5
source share
1 answer

Quote from the perfect answer to the question you related:

However, if the parameter was const, then get would not be considered triggered by a data race with other const calls to receive.

This is basically your answer. Make every call to get (on any tuple that is not fully protected by the mutex) in the const tuple, and you are safe.

This means that your code published is unsafe. Change it like this:

 void baz() { // vvvv just being explicit here auto const & tup = std::get<0>(static_cast<decltype(tuple) const &>(tuple)); std::lock_guard<std::mutex> lk(*std::get<2>(tup)); // Dereference std::get<0>(tup) and std::get<1>(tup), // use the pointed to objects at will, nothing else // Not ok, because it could interfer with the call in initialisation of tup of another thread // auto non_const_tup = std::get<0>(tuple) } 

Currently, the only solution I see is to use a tuple like:

 std::tuple< std::shared_pointer<std::mutex>, std::unique_pointer<std::tuple<Foo1*, Bar1*>> // Mutex and pointer to tuple for Foo2 and Bar2 > 

The required const will stick to everything (except the target pointers).

+3
source

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


All Articles