diff --git a/mingw.thread.h b/mingw.thread.h index caf333e..b0fff64 100644 --- a/mingw.thread.h +++ b/mingw.thread.h @@ -72,18 +72,22 @@ namespace detail template class ThreadFuncCall { - typedef std::tuple Tuple; - Func mFunc; + using Tuple = std::tuple::type...>; + typename std::decay::type mFunc; Tuple mArgs; template void callFunc(detail::IntSeq) { - detail::invoke(std::forward(mFunc), std::get(std::forward(mArgs)) ...); +// Note: Only called once (per thread) + detail::invoke(std::move(mFunc), std::move(std::get(mArgs)) ...); } public: ThreadFuncCall(Func&& aFunc, Args&&... aArgs) - :mFunc(std::forward(aFunc)), mArgs(std::forward(aArgs)...){} + : mFunc(std::forward(aFunc)), + mArgs(std::forward(aArgs)...) + { + } void callFunc() { diff --git a/tests/tests.cpp b/tests/tests.cpp index b4cb7ac..2e47add 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -312,6 +312,33 @@ int main() std::hash hasher; std::cout << "Hash:\t" << hasher(this_thread::get_id()) << "\n"; } + +// Regression test: Thread must copy any argument that is passed by value. + { + std::vector loop_threads; + std::atomic i_vals_touched [4];// { 0, 0, 0, 0 }; + for (int i = 0; i < 4; ++i) + i_vals_touched[i].store(0, std::memory_order_relaxed); + for (int i = 0; i < 4; ++i) + { + loop_threads.push_back(std::thread([&](int c) + { + log("For-loop test thread got value: %i", c); + i_vals_touched[c].fetch_add(1, std::memory_order_relaxed); + }, i)); + } + for (std::thread & thr : loop_threads) + thr.join(); + for (int i = 0; i < 4; ++i) + { + if (i_vals_touched[i] != 1) + { + log("FATAL: Threads are not copying arguments!"); + return 1; + } + } + } + std::thread t([](TestMove&& a, const char* b, int c) mutable { try