How to work around std::get<>()'s lack of concurency specification How to work around std::get<>()'s lack of concurency specification multithreading multithreading

How to work around std::get<>()'s lack of concurency specification


Push a proposal for std::get<>(std::tuple) to provide guarantees similar to std::vector<>, and document the fact that the code is only valid as of a yet unreleased version of the the standard.

I think this is the way to go, as it provides value for the entire C++ community and should not be a burden on implementers. It is also an excellent opportunity to write your first proposal.

I suggest doing that, and for now assuming that this will work, even though it is UB. If your software is super-critical (e.g. flight control system) and you want to be 100% sure that you are not relying on something that could break in the future... then implement your own tuple.


template<class...Ts>std::tuple< std::remove_reference_t<T>* >to_pointers( std::tuple<Ts...>& );template<class T0, class...Ts>std::array<T0, 1+sizeof...(Ts)>to_array( std::tuple<T0, Ts...> const& );

write these.

int main() {    data_t landing;    std::atomic<int> completed = 0;    // Whichever thread pings last will be the one performing foo()    auto ping = [&](){        if(++completed == 4) {            foo(landing);        }    };    auto arr = to_array(to_pointers(landing));    std::thread a([&](){ *arr[0] = 1; ping(); });    std::thread b([&](){ *arr[1] = 2; ping(); });    std::thread c([&](){ *arr[2] = 3; ping(); });    std::thread d([&](){ *arr[3] = 4; ping(); });    a.join();    b.join();    c.join();    d.join();    return 0;}

we access the tuple elements via pointers to them instead of via std::get. The problem is in the specification of std::get; once you have the independent pointers to the independent objects guaranteed to exist within the tuple, you are race condition free.

So we convert the tuple to an array of pointers in one thread (which is basically free), then use it in the threads safely.