From 76d85a10f6cda93eba29dad5372e8160af7289c8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 27 Feb 2019 22:26:35 +0100 Subject: Use multiple threads to parse --- src/std/thread.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 src/std/thread.c (limited to 'src/std/thread.c') diff --git a/src/std/thread.c b/src/std/thread.c new file mode 100644 index 0000000..f717865 --- /dev/null +++ b/src/std/thread.c @@ -0,0 +1,140 @@ +#include "../../include/std/thread.h" +#include "../../include/std/log.h" +#include +#include +#include +#include +#include +#include +#include + +static int thread_type_to_system_thread_type(amal_thread_type thread_type) { + switch(thread_type) { + case AMAL_THREAD_JOINABLE: return PTHREAD_CREATE_JOINABLE; + case AMAL_THREAD_DETACHED: return PTHREAD_CREATE_DETACHED; + } + assert(bool_false); + return PTHREAD_CREATE_JOINABLE; +} + +int amal_thread_create(amal_thread *self, amal_thread_type thread_type, const char *name, AmalThreadCallbackFunc callback_func, void *userdata) { + int result; + self->name = name; + self->thread_id = 0; + self->cancellable = bool_false; + self->destroyable = bool_false; + if((result = pthread_attr_init(&self->thread_attr)) != 0) { + perror("amal_thread_create"); + return result; + } + self->destroyable = bool_true; + if((result = pthread_attr_setdetachstate(&self->thread_attr, thread_type_to_system_thread_type(thread_type))) != 0) { + perror("amal_thread_create"); + return result; + } + if((result = pthread_create(&self->thread_id, NULL, callback_func, userdata)) != 0) { + perror("amal_thread_create"); + return result; + } + self->cancellable = bool_true; + return 0; +} + +int amal_thread_deinit(amal_thread *self) { + int r1; + int r2; + r1 = 0; + r2 = 0; + + if(self->cancellable) { + r1 = pthread_cancel(self->thread_id); + self->cancellable = bool_false; + } + if(self->destroyable) { + r2 = pthread_attr_destroy(&self->thread_attr); + self->destroyable = bool_false; + } + return r1 != 0 ? r1 : r2; +} + +int amal_thread_detach(amal_thread *self) { + int result_err; + int thread_type; + if((result_err = pthread_attr_getdetachstate(&self->thread_attr, &thread_type)) != 0) + return result_err; + if(thread_type != PTHREAD_CREATE_DETACHED) + return AMAL_THREAD_ERR; + if((result_err = pthread_detach(self->thread_id)) != 0) + return result_err; + self->cancellable = bool_false; + return 0; +} + +int amal_thread_join(amal_thread *self, void **result) { + int result_err; + int thread_type; + if((result_err = pthread_attr_getdetachstate(&self->thread_attr, &thread_type)) != 0) + return result_err; + if(thread_type != PTHREAD_CREATE_JOINABLE) + return AMAL_THREAD_NOT_JOINABLE; + if((result_err = pthread_join(self->thread_id, result)) != 0) + return result_err == EINVAL ? AMAL_THREAD_NOT_JOINABLE : result_err; + self->cancellable = bool_false; + return 0; +} + +void amal_mutex_init(amal_mutex *self) { + pthread_mutex_init(&self->mutex, NULL); + /* TODO: pthread_mutex_destroy in amal_mutex_deinit */ + self->lock_identifier = NULL; +} + +static long amal_process_get_id() { + return getpid(); +} + +static long amal_thread_get_id() { + return syscall(SYS_gettid); +} + +int amal_mutex_lock(amal_mutex *self, const char *lock_identifier) { + int result; + result = pthread_mutex_lock(&self->mutex); + self->lock_identifier = lock_identifier; + if(result == 0 && self->lock_identifier) { + amal_log_debug("amal_mutex_lock: mutex locked by thread %lu (%s), identification: %s", + amal_thread_get_id(), + amal_thread_is_main() ? "main" : "not main", + self->lock_identifier ? self->lock_identifier : "none"); + } + return result; +} + +int amal_mutex_unlock(amal_mutex *self) { + int result; + const char *identifier; + identifier = self->lock_identifier; + result = pthread_mutex_unlock(&self->mutex); + if(result == 0 && identifier) { + amal_log_debug("amal_mutex_unlock: mutex unlocked by thread %lu (%s), identification: %s", + amal_thread_get_id(), + amal_thread_is_main() ? "main" : "not main", + identifier ? identifier : "none"); + } + return result; +} + +void amal_mutex_tryunlock(amal_mutex *self) { + int _; + (void)_; + _ = amal_mutex_unlock(self); +} + +bool amal_thread_is_main() { + /* TODO: This only works for linux, use equivalent functions on other platforms */ + return amal_thread_get_id() == amal_process_get_id(); +} + +int amal_get_usable_thread_count() { + return get_nprocs(); +} \ No newline at end of file -- cgit v1.2.3