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& );
запишите их.
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;
}
мы получаем доступ к элементам кортежа через указатели на них, а не через std::get
.Проблема в спецификации std::get
;как только у вас есть независимые указатели на независимые объекты, которые гарантированно существуют в кортеже, вы свободны от состояния гонки.
Итак, мы конвертируем кортеж в массив указателей в одном потоке (который в основном свободен), затембезопасно используйте его в темах.