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

#include <vector>
6
#include <mutex>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

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;

TEST_CASE( "thread creation and joining", "[internal/base/thread.h]") {
    base_tests_visited = false;
    auto t1 = start_thread([]() { base_tests_visited = true; });
    t1.join();

    REQUIRE(base_tests_visited);
}

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

    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();

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

TEST_CASE( "spinlock protects concurrent counter", "[internal/base/spinlock.h]") {
37
    constexpr int num_iterations = 100000;
38 39 40
    int shared_counter = 0;
    spin_lock lock{};

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
    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();
            }
        });
56

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
        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<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();
79

80 81
        REQUIRE(shared_counter == 0);
    }
82
}