// http://preshing.com/20120515/memory-reordering-caught-in-the-act #include #include #include #include #include #include #include using namespace std::literals; int x, y, r1, r2; unsigned reorders = 0, iterations = 0; std::atomic run(true); std::mutex m1, m2, m3, m4; std::ranlux24_base e; std::uniform_int_distribution d(0, 7); auto rng = std::bind(d, e); void t1() { while(run) { m1.lock(); while (rng() != 0); x = 1; asm volatile ("":::"memory"); r1 = y; m3.unlock(); } } void t2() { while(run) { m2.lock(); while (rng() != 0); y = 1; asm volatile ("":::"memory"); r2 = x; m4.unlock(); } } void t3() { while (run) { x = 0; y = 0; m1.unlock(); m2.unlock(); m3.lock(); m4.lock(); if (r1 == 0 && r2 == 0) ++reorders; ++iterations; } } int main() { std::lock(m1, m2, m3, m4); std::jthread t[] = {std::jthread(t1), std::jthread(t2), std::jthread(t3)}; cpu_set_t cpus; CPU_ZERO(&cpus); CPU_SET(0, &cpus); for (auto& i: t) pthread_setaffinity_np(i.native_handle(), sizeof(cpu_set_t), &cpus); std::this_thread::sleep_for(500ms); run = false; m1.unlock(); m2.unlock(); for (auto& i: t) i.join(); std::cout << reorders << " reorders detected after " << iterations << " iterations" << std::endl; }