mirror of
https://github.com/boostorg/atomic.git
synced 2025-05-12 05:51:45 +00:00
This removes dependencies on Boost.Thread and Boost.Chrono, as well as their dependencies and potentially allows to test more compilers. In particular, this removes the dependency on Boost.Lexical cast, which no longer compiles with gcc 4.6 and 4.7.
77 lines
2.2 KiB
C++
77 lines
2.2 KiB
C++
// Copyright (c) 2020 Andrey Semashev
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// This is a fuzzing test for waiting and notifying operations.
|
|
// The test creates a number of threads exceeding the number of hardware threads, each of which
|
|
// blocks on the atomic object. The main thread then notifies one or all threads repeatedly,
|
|
// while incrementing the atomic object. The test ends when the atomic counter reaches the predefined limit.
|
|
// The goal of the test is to verify that (a) it doesn't crash and (b) all threads get unblocked in the end.
|
|
|
|
#include <boost/memory_order.hpp>
|
|
#include <boost/atomic/atomic.hpp>
|
|
|
|
#include <chrono>
|
|
#include <thread>
|
|
#include <memory>
|
|
#include <iostream>
|
|
#include <boost/config.hpp>
|
|
#include "test_clock.hpp"
|
|
#include "test_barrier.hpp"
|
|
|
|
boost::atomic< unsigned int > g_atomic(0u);
|
|
|
|
BOOST_CONSTEXPR_OR_CONST unsigned int loop_count = 4096u;
|
|
|
|
void thread_func(test_barrier* barrier)
|
|
{
|
|
barrier->arrive_and_wait();
|
|
|
|
unsigned int old_count = 0u;
|
|
while (true)
|
|
{
|
|
unsigned int new_count = g_atomic.wait(old_count, boost::memory_order_relaxed);
|
|
if (new_count >= loop_count)
|
|
break;
|
|
|
|
old_count = new_count;
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
const unsigned int thread_count = std::thread::hardware_concurrency() + 4u;
|
|
test_barrier barrier(thread_count + 1u);
|
|
std::unique_ptr< std::thread[] > threads(new std::thread[thread_count]);
|
|
|
|
for (unsigned int i = 0u; i < thread_count; ++i)
|
|
threads[i] = std::thread([&barrier]() { thread_func(&barrier); });
|
|
|
|
barrier.arrive_and_wait();
|
|
|
|
// Let the threads block on the atomic counter
|
|
std::this_thread::sleep_for(chrono::milliseconds(100));
|
|
|
|
while (true)
|
|
{
|
|
for (unsigned int i = 0u; i < thread_count; ++i)
|
|
{
|
|
g_atomic.opaque_add(1u, boost::memory_order_relaxed);
|
|
g_atomic.notify_one();
|
|
}
|
|
|
|
unsigned int old_count = g_atomic.fetch_add(1u, boost::memory_order_relaxed);
|
|
g_atomic.notify_all();
|
|
|
|
if ((old_count + 1u) >= loop_count)
|
|
break;
|
|
}
|
|
|
|
for (unsigned int i = 0u; i < thread_count; ++i)
|
|
threads[i].join();
|
|
|
|
return 0u;
|
|
}
|