Commit c1bcd2e0 by FritzFlorian

First draft of thread class using c++11 standard.

The first draft of the internal threading component is currently only implemented using the c++11 std::thread, pthread support will be added next.
parent 3e1aa956
...@@ -37,3 +37,6 @@ in our CI process and optional in other builds. To setup CMake builds ...@@ -37,3 +37,6 @@ in our CI process and optional in other builds. To setup CMake builds
with sanitizer enabled add the cmake option `-DTHREAD_SANITIZER=ON`. with sanitizer enabled add the cmake option `-DTHREAD_SANITIZER=ON`.
Please regularly test with thread sanitizer enabled and make sure to not Please regularly test with thread sanitizer enabled and make sure to not
keep the repository in a state where the sanitizer reports errors. keep the repository in a state where the sanitizer reports errors.
Consider reading [the section on common data races](https://github.com/google/sanitizers/wiki/ThreadSanitizerPopularDataRaces)
to get an idea of what we try to avoid in our code.
\ No newline at end of file
# List all required files here (cmake best practice to NOT automate this step!) # List all required files here (cmake best practice to NOT automate this step!)
add_library(pls STATIC add_library(pls STATIC
src/library.cpp include/pls/library.h) src/library.cpp include/pls/library.h
src/internal/base/thread.cpp include/pls/internal/base/thread.h)
# Settings for our project...
# ...pthreads or C++ 11 threads
option(USING_PTHREADS "Build the tests" ON)
if(USING_PTHREADS)
target_compile_definitions(pls PUBLIC USING_PTHREADS)
else()
target_compile_definitions(pls PUBLIC USING_CPP_THREADS)
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
target_include_directories(pls target_include_directories(pls
......
/**
* Abstraction for threading to allow porting.
* Currently using either pthread or C++ 11 threads.
*/
#ifndef PLS_THREAD_H
#define PLS_THREAD_H
// platform specific includes
#ifdef USING_PTHREADS
#include <pthread.h>
#elif USING_CPP_THREADS
#include <thread>
#else
#error "Please configure exactly one threading library!"
#endif
namespace pls {
namespace internal {
namespace base {
using thread_entrypoint = void();
// Thread local storage support
#ifdef USING_PTHREADS
pthread_key_t thr_id_key;
bool thr_id_key_created = false;
// forward declaration
int start_pthread_internal(void*);
#endif
#ifdef USING_CPP_THREADS
thread_local void* local_thread;
#endif
template<typename T>
class thread {
private:
// Handle to the native thread used
#ifdef USING_PTHREADS
friend int start_pthread_internal(void*);
pthread_t pthread_thread_;
thread_entrypoint entry_function_;
thread(thread_entrypoint entry_function, T local_object):
pthread_thread_(),
entry_function_(entry_function),
local_object_(local_object) {
if (!thr_id_key_created) {
pthread_key_create(&thr_id_key, nullptr);
thr_id_key_created = true;
}
pthread_create(&pthread_thread_, nullptr, start_pthread_internal, (void *)(this));
}
#endif
#ifdef USING_CPP_THREADS
std::thread std_thread_;
thread(thread_entrypoint entry_function, T local_object):
local_object_(local_object),
std_thread_([=](){
local_thread = this;
entry_function();
}) {};
#endif
public:
T local_object_;
/**
* Creates and starts a thread.
* NOT thread safe, best only use from one main thread managing the runtime!
*
* @param entry_function The entry function to run on the thread
* @param T local_object
*
* @return a handle to the newly created thread
*/
static thread start(thread_entrypoint entry_function, T local_object) {
return thread(entry_function, local_object);
}
void join() {
#ifdef USING_PTHREADS
// TODO
#endif
#ifdef USING_CPP_THREADS
std_thread_.join();
#endif
}
static void yield() {
#ifdef USING_PTHREADS
// TODO
#endif
#ifdef USING_CPP_THREADS
std::this_thread::yield();
#endif
}
static thread* get_current() {
#ifdef USING_PTHREADS
// TODO
#endif
#ifdef USING_CPP_THREADS
return (thread*) local_thread;
#endif
}
// make object move only
thread(thread&&) = default;
thread& operator=(thread&&) = 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;
pthread_setspecific(thr_id_key, thread_pointer);
my_thread->entry_function_();
pthread_exit(NULL);
}
#endif
}
}
}
#endif //PLS_THREAD_H
#include "pls/internal/base/thread.h"
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