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