Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

The following block of code:

  1. Is technically invalid, since std::get<>() is not thread safe. Reference: Is using `std::get<I>` on a `std::tuple` guaranteed to be thread-safe for different values of `I`?

  2. As far as I can tell, is effectively safe on all implentations of std::tuple<> in the wild right now, and the foreseeable future.

    #include <tuple>
    #include <atomic>
    #include <thread>

    // Out of my control
    using data_t = std::tuple<int, int, int, int>;
    void foo(data_t); 
    //

    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);
            }
        };

        std::thread a([&](){ std::get<0>(landing) = 1; ping(); });
        std::thread b([&](){ std::get<1>(landing) = 2; ping(); });
        std::thread c([&](){ std::get<2>(landing) = 3; ping(); });
        std::thread d([&](){ std::get<3>(landing) = 4; ping(); });

        a.join();
        b.join();
        c.join();
        d.join();

        return 0;
    }

To make matters even more fun, the actual code in question is chock-full of variadic templates, so writing a one-shot landing pad struct to handle that one scenario is not going to cut it. It has to be a general solution.

My current options are:

  • Effectively re-implement std::tuple<> with a reworded std::get<> documentation, which is a waste of time and a waste of code.
  • 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 verion of the standard.
  • ignore the issue, and rely on the fact that realistically, this will almost certainly always work.

None of those are particularly great in the short run... So my questions are:

  • Did I miss something that invalidates point #2?
  • Is there a better workaround that would allow the implementation to be technically valid while not having to support an excessive amount of extra code.
  • Any other opinions on the subject are welcome.
like image 809
Frank Avatar asked Jun 07 '19 16:06

Frank


1 Answers

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.

like image 116
Vittorio Romeo Avatar answered Oct 21 '22 07:10

Vittorio Romeo