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*>>
The required const will stick to everything (except the target pointers).
source share