From 1e4deb10a1f0bf0e0ec11e70fd4051b315c330e4 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 25 Jun 2023 19:03:02 +0300 Subject: [PATCH] Add rw_spinlock tests --- test/CMakeLists.txt | 10 +++++- test/Jamfile.v2 | 8 +++++ test/cfoa/rw_spinlock_test.cpp | 26 ++++++++++++++ test/cfoa/rw_spinlock_test2.cpp | 41 +++++++++++++++++++++ test/cfoa/rw_spinlock_test3.cpp | 49 +++++++++++++++++++++++++ test/cfoa/rw_spinlock_test4.cpp | 29 +++++++++++++++ test/cfoa/rw_spinlock_test5.cpp | 42 ++++++++++++++++++++++ test/cfoa/rw_spinlock_test6.cpp | 60 +++++++++++++++++++++++++++++++ test/cfoa/rw_spinlock_test7.cpp | 62 ++++++++++++++++++++++++++++++++ test/cfoa/rw_spinlock_test8.cpp | 64 +++++++++++++++++++++++++++++++++ 10 files changed, 390 insertions(+), 1 deletion(-) create mode 100644 test/cfoa/rw_spinlock_test.cpp create mode 100644 test/cfoa/rw_spinlock_test2.cpp create mode 100644 test/cfoa/rw_spinlock_test3.cpp create mode 100644 test/cfoa/rw_spinlock_test4.cpp create mode 100644 test/cfoa/rw_spinlock_test5.cpp create mode 100644 test/cfoa/rw_spinlock_test6.cpp create mode 100644 test/cfoa/rw_spinlock_test7.cpp create mode 100644 test/cfoa/rw_spinlock_test8.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f9dd0e45..5b9307e1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 @@ -159,5 +159,13 @@ cfoa_tests(SOURCES cfoa/exception_erase_tests.cpp) cfoa_tests(SOURCES cfoa/exception_constructor_tests.cpp) cfoa_tests(SOURCES cfoa/exception_assign_tests.cpp) cfoa_tests(SOURCES cfoa/exception_merge_tests.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test2.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test3.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test4.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test5.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test6.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test7.cpp) +cfoa_tests(SOURCES cfoa/rw_spinlock_test8.cpp) endif() diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 4e256e2a..1ad15a18 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -195,6 +195,14 @@ local CFOA_TESTS = exception_constructor_tests exception_assign_tests exception_merge_tests + rw_spinlock_test + rw_spinlock_test2 + rw_spinlock_test3 + rw_spinlock_test4 + rw_spinlock_test5 + rw_spinlock_test6 + rw_spinlock_test7 + rw_spinlock_test8 ; for local test in $(CFOA_TESTS) diff --git a/test/cfoa/rw_spinlock_test.cpp b/test/cfoa/rw_spinlock_test.cpp new file mode 100644 index 00000000..c5eac602 --- /dev/null +++ b/test/cfoa/rw_spinlock_test.cpp @@ -0,0 +1,26 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +// Sanity check only + +static rw_spinlock sp; +static rw_spinlock sp2; + +int main() +{ + sp.lock(); + sp2.lock(); + sp.unlock(); + sp2.unlock(); + + { + std::lock_guard lock( sp ); + std::lock_guard lock2( sp2 ); + } +} diff --git a/test/cfoa/rw_spinlock_test2.cpp b/test/cfoa/rw_spinlock_test2.cpp new file mode 100644 index 00000000..2c9f9242 --- /dev/null +++ b/test/cfoa/rw_spinlock_test2.cpp @@ -0,0 +1,41 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static rw_spinlock sp; +static rw_spinlock sp2; + +int main() +{ + 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 lock( sp ); + BOOST_TEST( !sp.try_lock() ); + std::lock_guard lock2( sp2 ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( !sp2.try_lock() ); + } + + return boost::report_errors(); +} diff --git a/test/cfoa/rw_spinlock_test3.cpp b/test/cfoa/rw_spinlock_test3.cpp new file mode 100644 index 00000000..d1826a66 --- /dev/null +++ b/test/cfoa/rw_spinlock_test3.cpp @@ -0,0 +1,49 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static int count = 0; +static rw_spinlock sp; + +void f( int k, int n ) +{ + std::printf( "Thread %d started.\n", k ); + + for( int i = 0; i < n; ++i ) + { + std::lock_guard lock( sp ); + ++count; + } + + std::printf( "Thread %d finished.\n", k ); +} + +int main() +{ + 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( f, i, N ); + } + + for( int i = 0; i < M; ++i ) + { + th[ i ].join(); + } + + BOOST_TEST_EQ( count, N * M ); + + return boost::report_errors(); +} diff --git a/test/cfoa/rw_spinlock_test4.cpp b/test/cfoa/rw_spinlock_test4.cpp new file mode 100644 index 00000000..65b04fdd --- /dev/null +++ b/test/cfoa/rw_spinlock_test4.cpp @@ -0,0 +1,29 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static rw_spinlock sp; +static rw_spinlock sp2; + +int main() +{ + sp.lock(); + sp2.lock_shared(); + sp2.lock_shared(); + + sp.unlock(); + sp2.unlock_shared(); + sp2.unlock_shared(); + + { + std::lock_guard lock( sp ); + boost::compat::shared_lock lock2( sp2 ); + boost::compat::shared_lock lock3( sp2 ); + } +} diff --git a/test/cfoa/rw_spinlock_test5.cpp b/test/cfoa/rw_spinlock_test5.cpp new file mode 100644 index 00000000..5e542ee4 --- /dev/null +++ b/test/cfoa/rw_spinlock_test5.cpp @@ -0,0 +1,42 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static rw_spinlock sp; + +int main() +{ + { + 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 lock( sp ); + BOOST_TEST( !sp.try_lock_shared() ); + } + + { + boost::compat::shared_lock lock( sp ); + BOOST_TEST( !sp.try_lock() ); + BOOST_TEST( sp.try_lock_shared() ); + sp.unlock_shared(); + } + + return boost::report_errors(); +} diff --git a/test/cfoa/rw_spinlock_test6.cpp b/test/cfoa/rw_spinlock_test6.cpp new file mode 100644 index 00000000..9d0562c2 --- /dev/null +++ b/test/cfoa/rw_spinlock_test6.cpp @@ -0,0 +1,60 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static int count = 0; +static rw_spinlock sp; + +void f( int k, int n ) +{ + std::printf( "Thread %d started.\n", k ); + + int i = 0; + + for( ;; ++i ) + { + { + boost::compat::shared_lock lock( sp ); + if( count >= n ) break; + } + + { + std::lock_guard lock( sp ); + if( count >= n ) break; + ++count; + } + } + + std::printf( "Thread %d finished (%i iterations).\n", k, i ); +} + +int main() +{ + int const N = 1000000; // total iterations + int const M = 8; // threads + + std::thread th[ M ]; + + for( int i = 0; i < M; ++i ) + { + th[ i ] = std::thread( f, i, N ); + } + + for( int i = 0; i < M; ++i ) + { + th[ i ].join(); + } + + BOOST_TEST_EQ( count, N ); + + return boost::report_errors(); +} diff --git a/test/cfoa/rw_spinlock_test7.cpp b/test/cfoa/rw_spinlock_test7.cpp new file mode 100644 index 00000000..be88df26 --- /dev/null +++ b/test/cfoa/rw_spinlock_test7.cpp @@ -0,0 +1,62 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static int count = 0; +static rw_spinlock sp; + +void f( int k, int n ) +{ + std::printf( "Thread %d started.\n", k ); + + int i = 0; + + for( ;; ++i ) + { + int oldc; + + { + boost::compat::shared_lock lock( sp ); + if( count >= n ) break; + oldc = count; + } + + { + std::lock_guard lock( sp ); + if( count == oldc ) ++count; + } + } + + std::printf( "Thread %d finished (%i iterations).\n", k, i ); +} + +int main() +{ + int const N = 1000000; // total iterations + int const M = 8; // threads + + std::thread th[ M ]; + + for( int i = 0; i < M; ++i ) + { + th[ i ] = std::thread( f, i, N ); + } + + for( int i = 0; i < M; ++i ) + { + th[ i ].join(); + } + + BOOST_TEST_EQ( count, N ); + + return boost::report_errors(); +} diff --git a/test/cfoa/rw_spinlock_test8.cpp b/test/cfoa/rw_spinlock_test8.cpp new file mode 100644 index 00000000..7a604265 --- /dev/null +++ b/test/cfoa/rw_spinlock_test8.cpp @@ -0,0 +1,64 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include + +using boost::unordered::detail::foa::rw_spinlock; + +static int count = 0; +static rw_spinlock sp; + +void f( int k, int m, int n ) +{ + std::printf( "Thread %d of %d started.\n", k, m ); + + for( int i = 0; i < n; ++i ) + { + int oldc; + + for( ;; ) + { + { + boost::compat::shared_lock lock( sp ); + oldc = count; + } + + if( oldc % m == k ) break; + } + + { + std::lock_guard lock( sp ); + if( count == oldc ) ++count; + } + } + + std::printf( "Thread %d of %d finished.\n", k, m ); +} + +int main() +{ + int const N = 1000; // total iterations + int const M = 4; // threads + + std::thread th[ M ]; + + for( int i = 0; i < M; ++i ) + { + th[ i ] = std::thread( f, i, M, N ); + } + + for( int i = 0; i < M; ++i ) + { + th[ i ].join(); + } + + BOOST_TEST_EQ( count, N * M ); + + return boost::report_errors(); +}