forked from boostorg/unordered
Add explicit tests for rw_spinlock
This commit is contained in:
committed by
Peter Dimov
parent
6ee93f17e4
commit
0d2eaa0b21
@ -140,6 +140,7 @@ foa_tests(SOURCES exception/merge_exception_tests.cpp)
|
|||||||
|
|
||||||
# CFOA tests
|
# CFOA tests
|
||||||
|
|
||||||
|
cfoa_tests(SOURCES cfoa/rw_spinlock_tests.cpp)
|
||||||
cfoa_tests(SOURCES cfoa/latch_tests.cpp)
|
cfoa_tests(SOURCES cfoa/latch_tests.cpp)
|
||||||
cfoa_tests(SOURCES cfoa/insert_tests.cpp)
|
cfoa_tests(SOURCES cfoa/insert_tests.cpp)
|
||||||
cfoa_tests(SOURCES cfoa/erase_tests.cpp)
|
cfoa_tests(SOURCES cfoa/erase_tests.cpp)
|
||||||
|
@ -177,6 +177,7 @@ alias foa_tests :
|
|||||||
|
|
||||||
local CFOA_TESTS =
|
local CFOA_TESTS =
|
||||||
latch_tests
|
latch_tests
|
||||||
|
rw_spinlock_tests
|
||||||
insert_tests
|
insert_tests
|
||||||
erase_tests
|
erase_tests
|
||||||
try_emplace_tests
|
try_emplace_tests
|
||||||
|
255
test/cfoa/rw_spinlock_tests.cpp
Normal file
255
test/cfoa/rw_spinlock_tests.cpp
Normal 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()
|
Reference in New Issue
Block a user