diff --git a/lib/pls/CMakeLists.txt b/lib/pls/CMakeLists.txt index 9226c17..c6684e2 100644 --- a/lib/pls/CMakeLists.txt +++ b/lib/pls/CMakeLists.txt @@ -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 diff --git a/lib/pls/include/pls/internal/base/thread.h b/lib/pls/include/pls/internal/base/thread.h index b6202e9..3eaa540 100644 --- a/lib/pls/include/pls/internal/base/thread.h +++ b/lib/pls/include/pls/internal/base/thread.h @@ -7,9 +7,9 @@ #define PLS_THREAD_H // platform specific includes -#ifdef USING_PTHREADS +#ifdef PLS_USING_PTHREADS #include -#elif USING_CPP_THREADS +#elif PLS_USING_CPP_THREADS #include #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 + 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(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, (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 + void* start_pthread_internal(void* thread_pointer) { + auto* my_thread = (thread*)thread_pointer; pthread_setspecific(thr_id_key, thread_pointer); my_thread->entry_function_(); - pthread_exit(NULL); + pthread_exit(nullptr); } #endif } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 929af12..0ca48e9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,4 +1,5 @@ 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 diff --git a/test/thread_tests.cpp b/test/thread_tests.cpp new file mode 100644 index 0000000..51551bb --- /dev/null +++ b/test/thread_tests.cpp @@ -0,0 +1,24 @@ +#include +#include + +#include + +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::start([]() { visited = true; }, 0); + t1.join(); + + REQUIRE(visited); +} + +TEST_CASE( "thread state", "[internal/base/thread.h]") { + auto t1 = thread::start([]() { REQUIRE(thread::get_current()->local_object_ == 1); }, 1); + auto t2 = thread::start([]() { REQUIRE(thread::get_current()->local_object_ == "Hello"); }, "Hello"); + t1.join(); + t2.join(); +} \ No newline at end of file