#pragma once #include "../relacy/relacy.hpp" #include "../relacy/dyn_thread.hpp" struct dyn_thread_basic_test : rl::test_suite { static unsigned const dynamic_thread_count = 4; rl::var data1; rl::var data2; rl::atomic data3; void before() { data3($) = 0; } static void* thread1(void* p) { dyn_thread_basic_test& self = *(dyn_thread_basic_test*)p; self.data1($) = 1; return 0; } static void* thread2(void* p) { dyn_thread_basic_test& self = *(dyn_thread_basic_test*)p; self.data2($) = 2; return 0; } static void* thread3(void* p) { dyn_thread_basic_test& self = *(dyn_thread_basic_test*)p; self.data3.store(3, rl::memory_order_relaxed); return 0; } void thread(unsigned index) { if (index == 0) { rl::dyn_thread t1; t1.start(&dyn_thread_basic_test::thread1, this); rl::dyn_thread t2; t2.start(&dyn_thread_basic_test::thread2, this); t1.join(); t2.join(); RL_ASSERT(data1($) == 1); RL_ASSERT(data2($) == 2); } else if (index == 1) { rl::dyn_thread t1; t1.start(&dyn_thread_basic_test::thread3, this); while (data3.load(rl::memory_order_relaxed) != 3) rl::yield(1, $); t1.join(); } else { RL_ASSERT(false); } } }; struct dyn_thread_win32_test : rl::test_suite { static unsigned const dynamic_thread_count = 4; rl::var data1; rl::var data2; rl::atomic data3; void before() { data3($) = 0; } static unsigned long RL_STDCALL thread1(void* p) { dyn_thread_win32_test& self = *(dyn_thread_win32_test*)p; self.data1($) = 1; return 0; } static unsigned long RL_STDCALL thread2(void* p) { dyn_thread_win32_test& self = *(dyn_thread_win32_test*)p; self.data2($) = 2; return 0; } static unsigned long RL_STDCALL thread3(void* p) { dyn_thread_win32_test& self = *(dyn_thread_win32_test*)p; self.data3.store(3, rl::memory_order_relaxed); return 0; } void thread(unsigned index) { if (index == 0) { HANDLE threads [2]; threads[0] = CreateThread(0, 0, &dyn_thread_win32_test::thread1, this, 0, 0); threads[1] = CreateThread(0, 0, &dyn_thread_win32_test::thread2, this, 0, 0); WaitForMultipleObjects(2, threads, 1, INFINITE); RL_ASSERT(VAR(data1) == 1); RL_ASSERT(VAR(data2) == 2); } else if (index == 1) { HANDLE th = CreateThread(0, 0, &dyn_thread_win32_test::thread3, this, 0, 0); while (data3.load(rl::memory_order_relaxed) != 3) rl::yield(1, $); WaitForSingleObject(th, INFINITE); } else { RL_ASSERT(false); } } }; struct dyn_thread_visibility_test : rl::test_suite { static unsigned const dynamic_thread_count = 1; rl::var data; static unsigned long RL_STDCALL thread(void* p) { dyn_thread_visibility_test& self = *(dyn_thread_visibility_test*)p; RL_ASSERT(self.data($) == 1); self.data($) = 2; return 0; } void thread(unsigned /*index*/) { data($) = 1; HANDLE th = CreateThread(0, 0, &dyn_thread_visibility_test::thread, this, 0, 0); WaitForSingleObject(th, INFINITE); RL_ASSERT(data($) == 2); } };