Compare commits

...

2 Commits

Author SHA1 Message Date
6c24c30c42 Update test/CMakeLists.txt 2023-06-25 18:20:36 +03:00
0d2eaa0b21 Add explicit tests for rw_spinlock 2023-06-25 13:05:10 +03:00
3 changed files with 258 additions and 1 deletions

View File

@ -20,7 +20,7 @@ function(foa_tests)
endfunction()
function(cfoa_tests)
boost_test(PREFIX boost_unordered_cfoa LINK_LIBRARIES Threads::Threads ${ARGN})
boost_test(PREFIX boost_unordered_cfoa LINK_LIBRARIES Boost::compat Threads::Threads ${ARGN})
endfunction()
# FCA tests
@ -140,6 +140,7 @@ foa_tests(SOURCES exception/merge_exception_tests.cpp)
# CFOA tests
cfoa_tests(SOURCES cfoa/rw_spinlock_tests.cpp)
cfoa_tests(SOURCES cfoa/latch_tests.cpp)
cfoa_tests(SOURCES cfoa/insert_tests.cpp)
cfoa_tests(SOURCES cfoa/erase_tests.cpp)

View File

@ -177,6 +177,7 @@ alias foa_tests :
local CFOA_TESTS =
latch_tests
rw_spinlock_tests
insert_tests
erase_tests
try_emplace_tests

View File

@ -0,0 +1,255 @@
// Copyright 2023 Peter Dimov
// Copyright 2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include "helpers.hpp"
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <mutex>
#include <thread>
using boost::unordered::detail::foa::rw_spinlock;
static int count = 0;
UNORDERED_AUTO_TEST (rw_spinlock_test) {
rw_spinlock sp, sp2;
sp.lock();
sp2.lock();
sp.unlock();
sp2.unlock();
{
std::lock_guard<rw_spinlock> lock(sp);
std::lock_guard<rw_spinlock> lock2(sp2);
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test2) {
rw_spinlock sp, sp2;
BOOST_TEST(sp.try_lock());
BOOST_TEST(!sp.try_lock());
BOOST_TEST(sp2.try_lock());
BOOST_TEST(!sp.try_lock());
BOOST_TEST(!sp2.try_lock());
sp.unlock();
sp2.unlock();
sp.lock();
BOOST_TEST(!sp.try_lock());
sp2.lock();
BOOST_TEST(!sp.try_lock());
BOOST_TEST(!sp2.try_lock());
sp.unlock();
sp2.unlock();
{
std::lock_guard<rw_spinlock> lock(sp);
BOOST_TEST(!sp.try_lock());
std::lock_guard<rw_spinlock> lock2(sp2);
BOOST_TEST(!sp.try_lock());
BOOST_TEST(!sp2.try_lock());
}
}
void f(rw_spinlock& sp, int n)
{
for (int i = 0; i < n; ++i) {
std::lock_guard<rw_spinlock> lock(sp);
++count;
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test3) {
count = 0;
rw_spinlock sp;
int const N = 1000000; // iterations
int const M = 8; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
th[i] = std::thread([=, &sp] { f(sp, N); });
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N * M);
}
UNORDERED_AUTO_TEST (rw_spinlock_test4) {
rw_spinlock sp, sp2;
sp.lock();
sp2.lock_shared();
sp2.lock_shared();
sp.unlock();
sp2.unlock_shared();
sp2.unlock_shared();
{
std::lock_guard<rw_spinlock> lock(sp);
boost::compat::shared_lock<rw_spinlock> lock2(sp2);
boost::compat::shared_lock<rw_spinlock> lock3(sp2);
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test5) {
rw_spinlock sp;
{
BOOST_TEST(sp.try_lock_shared());
BOOST_TEST(sp.try_lock_shared());
sp.unlock_shared();
sp.unlock_shared();
}
{
BOOST_TEST(sp.try_lock());
BOOST_TEST(!sp.try_lock_shared());
sp.unlock();
}
{
std::lock_guard<rw_spinlock> lock(sp);
BOOST_TEST(!sp.try_lock_shared());
}
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
BOOST_TEST(!sp.try_lock());
BOOST_TEST(sp.try_lock_shared());
sp.unlock_shared();
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test6) {
count = 0;
rw_spinlock sp;
int const N = 1000000; // total iterations
int const M = 8; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
int n = N;
th[i] = std::thread([n, &sp] {
for (;;) {
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
if (count >= n)
break;
}
{
std::lock_guard<rw_spinlock> lock(sp);
if (count >= n)
break;
++count;
}
}
});
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N);
}
UNORDERED_AUTO_TEST (rw_spinlock_test7) {
rw_spinlock sp;
int const N = 1000000; // total iterations
int const M = 8; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
int n = N;
th[i] = std::thread([=, &sp] {
for (;;) {
int oldc;
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
if (count >= n)
break;
oldc = count;
}
{
std::lock_guard<rw_spinlock> lock(sp);
if (count == oldc)
++count;
}
}
});
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N);
}
UNORDERED_AUTO_TEST (rw_spinlock_test8) {
count = 0;
rw_spinlock sp;
int const N = 1000; // total iterations
int const M = 4; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
int k = i;
int m = M;
int n = N;
th[i] = std::thread([k, m, n, &sp] {
for (int j = 0; j < n; ++j) {
int oldc;
for (;;) {
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
oldc = count;
}
if (oldc % m == k)
break;
}
{
std::lock_guard<rw_spinlock> lock(sp);
if (count == oldc)
++count;
}
}
});
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N * M);
}
RUN_TESTS()