From 0599cfdc93a675d6461cb570bf4f198c89cdd86a Mon Sep 17 00:00:00 2001 From: FritzFlorian Date: Wed, 20 Mar 2019 13:01:36 +0100 Subject: [PATCH] Add std::lock_guard test for spin_lock. --- lib/pls/include/pls/internal/base/spin_lock.h | 15 ++------------- lib/pls/src/internal/base/spin_lock.cpp | 14 +++++++++++++- test/base_tests.cpp | 59 +++++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 56 insertions(+), 32 deletions(-) diff --git a/lib/pls/include/pls/internal/base/spin_lock.h b/lib/pls/include/pls/internal/base/spin_lock.h index 880a521..5236e9f 100644 --- a/lib/pls/include/pls/internal/base/spin_lock.h +++ b/lib/pls/include/pls/internal/base/spin_lock.h @@ -17,19 +17,8 @@ namespace pls { public: spin_lock(): flag_{ATOMIC_FLAG_INIT}, yield_at_tries_{1024} {}; - void lock() { - int tries = 0; - while (flag_.test_and_set(std::memory_order_acquire)) { - tries++; - if (tries % yield_at_tries_ == 0) { - this_thread::yield(); - } - } - } - - void unlock() { - flag_.clear(std::memory_order_release); - } + void lock(); + void unlock(); }; } } diff --git a/lib/pls/src/internal/base/spin_lock.cpp b/lib/pls/src/internal/base/spin_lock.cpp index c0b06f7..10f6978 100644 --- a/lib/pls/src/internal/base/spin_lock.cpp +++ b/lib/pls/src/internal/base/spin_lock.cpp @@ -3,7 +3,19 @@ namespace pls { namespace internal { namespace base { - // implementation in header (inlining) + void spin_lock::lock() { + int tries = 0; + while (flag_.test_and_set(std::memory_order_acquire)) { + tries++; + if (tries % yield_at_tries_ == 0) { + this_thread::yield(); + } + } + } + + void spin_lock::unlock() { + flag_.clear(std::memory_order_release); + } } } } diff --git a/test/base_tests.cpp b/test/base_tests.cpp index d3c5ba9..7c7b990 100644 --- a/test/base_tests.cpp +++ b/test/base_tests.cpp @@ -3,6 +3,7 @@ #include #include +#include using namespace pls::internal::base; using namespace std; @@ -33,27 +34,49 @@ TEST_CASE( "thread state", "[internal/base/thread.h]") { } TEST_CASE( "spinlock protects concurrent counter", "[internal/base/spinlock.h]") { - constexpr int num_iterations = 1000000; + constexpr int num_iterations = 100000; int shared_counter = 0; spin_lock lock{}; - auto t1 = start_thread([&] () { - for (int i = 0; i < num_iterations; i++) { - lock.lock(); - shared_counter++; - lock.unlock(); - } - }); - auto t2 = start_thread([&] () { - for (int i = 0; i < num_iterations; i++) { - lock.lock(); - shared_counter--; - lock.unlock(); - } - }); + SECTION( "lock can be used by itself" ) { + auto t1 = start_thread([&]() { + for (int i = 0; i < num_iterations; i++) { + lock.lock(); + shared_counter++; + lock.unlock(); + } + }); + auto t2 = start_thread([&]() { + for (int i = 0; i < num_iterations; i++) { + lock.lock(); + shared_counter--; + lock.unlock(); + } + }); - t1.join(); - t2.join(); + t1.join(); + t2.join(); + + REQUIRE(shared_counter == 0); + } + + SECTION( "lock can be used with std::lock_guard" ) { + auto t1 = start_thread([&]() { + for (int i = 0; i < num_iterations; i++) { + std::lock_guard my_lock{lock}; + shared_counter++; + } + }); + auto t2 = start_thread([&]() { + for (int i = 0; i < num_iterations; i++) { + std::lock_guard my_lock{lock}; + shared_counter--; + } + }); + + t1.join(); + t2.join(); - REQUIRE(shared_counter == 0); + REQUIRE(shared_counter == 0); + } } -- libgit2 0.26.0