Commit 17aee013 by FritzFlorian

Add pthread support to threading abstraction.

parent c1bcd2e0
Pipeline #1088 failed with stages
in 2 minutes 51 seconds
......@@ -7,9 +7,9 @@ add_library(pls STATIC
# ...pthreads or C++ 11 threads
option(USING_PTHREADS "Build the tests" ON)
if(USING_PTHREADS)
target_compile_definitions(pls PUBLIC USING_PTHREADS)
target_compile_definitions(pls PUBLIC PLS_USING_PTHREADS)
else()
target_compile_definitions(pls PUBLIC USING_CPP_THREADS)
target_compile_definitions(pls PUBLIC PLS_USING_CPP_THREADS)
endif()
# Add everything in `./include` to be in the include path of this project
......
......@@ -7,9 +7,9 @@
#define PLS_THREAD_H
// platform specific includes
#ifdef USING_PTHREADS
#ifdef PLS_USING_PTHREADS
#include <pthread.h>
#elif USING_CPP_THREADS
#elif PLS_USING_CPP_THREADS
#include <thread>
#else
#error "Please configure exactly one threading library!"
......@@ -21,13 +21,14 @@ namespace pls {
using thread_entrypoint = void();
// Thread local storage support
#ifdef USING_PTHREADS
#ifdef PLS_USING_PTHREADS
pthread_key_t thr_id_key;
bool thr_id_key_created = false;
// forward declaration
int start_pthread_internal(void*);
template<typename T>
void* start_pthread_internal(void*);
#endif
#ifdef USING_CPP_THREADS
#ifdef PLS_USING_CPP_THREADS
thread_local void* local_thread;
#endif
......@@ -36,11 +37,11 @@ namespace pls {
class thread {
private:
// Handle to the native thread used
#ifdef USING_PTHREADS
friend int start_pthread_internal(void*);
#ifdef PLS_USING_PTHREADS
friend void* start_pthread_internal<T>(void*);
pthread_t pthread_thread_;
thread_entrypoint entry_function_;
thread_entrypoint* entry_function_;
thread(thread_entrypoint entry_function, T local_object):
pthread_thread_(),
......@@ -51,10 +52,10 @@ namespace pls {
thr_id_key_created = true;
}
pthread_create(&pthread_thread_, nullptr, start_pthread_internal, (void *)(this));
pthread_create(&pthread_thread_, nullptr, start_pthread_internal<T>, (void *)(this));
}
#endif
#ifdef USING_CPP_THREADS
#ifdef PLS_USING_CPP_THREADS
std::thread std_thread_;
thread(thread_entrypoint entry_function, T local_object):
......@@ -81,46 +82,47 @@ namespace pls {
}
void join() {
#ifdef USING_PTHREADS
// TODO
#ifdef PLS_USING_PTHREADS
pthread_join(pthread_thread_, nullptr);
#endif
#ifdef USING_CPP_THREADS
#ifdef PLS_USING_CPP_THREADS
std_thread_.join();
#endif
}
static void yield() {
#ifdef USING_PTHREADS
// TODO
#ifdef PLS_USING_PTHREADS
pthread_yield();
#endif
#ifdef USING_CPP_THREADS
#ifdef PLS_USING_CPP_THREADS
std::this_thread::yield();
#endif
}
static thread* get_current() {
#ifdef USING_PTHREADS
// TODO
#ifdef PLS_USING_PTHREADS
return (thread*) pthread_getspecific(thr_id_key);
#endif
#ifdef USING_CPP_THREADS
#ifdef PLS_USING_CPP_THREADS
return (thread*) local_thread;
#endif
}
// make object move only
thread(thread&&) = default;
thread& operator=(thread&&) = default;
thread(thread&&) noexcept = default;
thread& operator=(thread&&) noexcept = default;
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
};
#ifdef USING_PTHREADS
int start_pthread_internal(void* thread_pointer) {
thread* my_thread = (thread*)thread_pointer;
#ifdef PLS_USING_PTHREADS
template<typename T>
void* start_pthread_internal(void* thread_pointer) {
auto* my_thread = (thread<T>*)thread_pointer;
pthread_setspecific(thr_id_key, thread_pointer);
my_thread->entry_function_();
pthread_exit(NULL);
pthread_exit(nullptr);
}
#endif
}
......
add_executable(tests
main.cpp
example_tests.cpp)
example_tests.cpp
thread_tests.cpp)
target_link_libraries(tests catch2 pls)
\ No newline at end of file
#include <catch.hpp>
#include <pls/internal/base/thread.h>
#include <string>
using namespace pls::internal::base;
using namespace std;
static bool visited;
TEST_CASE( "thread creation and joining", "[internal/base/thread.h]") {
visited = false;
auto t1 = thread<int>::start([]() { visited = true; }, 0);
t1.join();
REQUIRE(visited);
}
TEST_CASE( "thread state", "[internal/base/thread.h]") {
auto t1 = thread<int>::start([]() { REQUIRE(thread<int>::get_current()->local_object_ == 1); }, 1);
auto t2 = thread<string>::start([]() { REQUIRE(thread<string>::get_current()->local_object_ == "Hello"); }, "Hello");
t1.join();
t2.join();
}
\ No newline at end of file
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