Commit 0599cfdc by FritzFlorian

Add std::lock_guard test for spin_lock.

parent 51cc6572
Pipeline #1100 failed with stages
in 1 minute 35 seconds
...@@ -17,19 +17,8 @@ namespace pls { ...@@ -17,19 +17,8 @@ namespace pls {
public: public:
spin_lock(): flag_{ATOMIC_FLAG_INIT}, yield_at_tries_{1024} {}; spin_lock(): flag_{ATOMIC_FLAG_INIT}, yield_at_tries_{1024} {};
void lock() { void lock();
int tries = 0; void unlock();
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);
}
}; };
} }
} }
......
...@@ -3,7 +3,19 @@ ...@@ -3,7 +3,19 @@
namespace pls { namespace pls {
namespace internal { namespace internal {
namespace base { 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);
}
} }
} }
} }
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <pls/internal/base/spin_lock.h> #include <pls/internal/base/spin_lock.h>
#include <vector> #include <vector>
#include <mutex>
using namespace pls::internal::base; using namespace pls::internal::base;
using namespace std; using namespace std;
...@@ -33,27 +34,49 @@ TEST_CASE( "thread state", "[internal/base/thread.h]") { ...@@ -33,27 +34,49 @@ TEST_CASE( "thread state", "[internal/base/thread.h]") {
} }
TEST_CASE( "spinlock protects concurrent counter", "[internal/base/spinlock.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; int shared_counter = 0;
spin_lock lock{}; spin_lock lock{};
auto t1 = start_thread([&] () { SECTION( "lock can be used by itself" ) {
for (int i = 0; i < num_iterations; i++) { auto t1 = start_thread([&]() {
lock.lock(); for (int i = 0; i < num_iterations; i++) {
shared_counter++; lock.lock();
lock.unlock(); shared_counter++;
} lock.unlock();
}); }
auto t2 = start_thread([&] () { });
for (int i = 0; i < num_iterations; i++) { auto t2 = start_thread([&]() {
lock.lock(); for (int i = 0; i < num_iterations; i++) {
shared_counter--; lock.lock();
lock.unlock(); shared_counter--;
} lock.unlock();
}); }
});
t1.join(); t1.join();
t2.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<spin_lock> my_lock{lock};
shared_counter++;
}
});
auto t2 = start_thread([&]() {
for (int i = 0; i < num_iterations; i++) {
std::lock_guard<spin_lock> my_lock{lock};
shared_counter--;
}
});
t1.join();
t2.join();
REQUIRE(shared_counter == 0); REQUIRE(shared_counter == 0);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment