base_tests.cpp 2.22 KB
Newer Older
1 2 3
#include <catch.hpp>
#include <pls/internal/base/thread.h>
#include <pls/internal/base/spin_lock.h>
FritzFlorian committed
4
#include <pls/internal/base/system_details.h>
5 6

#include <vector>
7
#include <mutex>
8 9 10 11 12 13 14 15

using namespace pls::internal::base;
using namespace std;

static bool base_tests_visited;
static int base_tests_local_value_one;
static vector<int> base_tests_local_value_two;

16 17 18 19
TEST_CASE("thread creation and joining", "[internal/data_structures/thread.h]") {
  base_tests_visited = false;
  auto t1 = start_thread([]() { base_tests_visited = true; });
  t1.join();
20

21
  REQUIRE(base_tests_visited);
22 23
}

24 25 26
TEST_CASE("thread state", "[internal/data_structures/thread.h]") {
  int state_one = 1;
  vector<int> state_two{1, 2};
27

28 29 30 31
  auto t1 = start_thread([]() { base_tests_local_value_one = *this_thread::state<int>(); }, &state_one);
  auto t2 = start_thread([]() { base_tests_local_value_two = *this_thread::state<vector<int>>(); }, &state_two);
  t1.join();
  t2.join();
32

33 34
  REQUIRE(base_tests_local_value_one == 1);
  REQUIRE(base_tests_local_value_two == vector<int>{1, 2});
35 36
}

37 38
int base_tests_shared_counter;

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
TEST_CASE("spinlock protects concurrent counter", "[internal/data_structures/spinlock.h]") {
  constexpr int num_iterations = 1000000;
  base_tests_shared_counter = 0;
  spin_lock lock{};

  SECTION("lock can be used by itself") {
    auto t1 = start_thread([&]() {
      for (int i = 0; i < num_iterations; i++) {
        lock.lock();
        base_tests_shared_counter++;
        lock.unlock();
      }
    });
    auto t2 = start_thread([&]() {
      for (int i = 0; i < num_iterations; i++) {
        lock.lock();
        base_tests_shared_counter--;
        lock.unlock();
      }
    });

    t1.join();
    t2.join();

    REQUIRE(base_tests_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};
        base_tests_shared_counter++;
      }
    });
    auto t2 = start_thread([&]() {
      for (int i = 0; i < num_iterations; i++) {
        std::lock_guard<spin_lock> my_lock{lock};
        base_tests_shared_counter--;
      }
    });

    t1.join();
    t2.join();

    REQUIRE(base_tests_shared_counter == 0);
  }
85
}