From: Hans-Kristian Arntzen Subject: [PATCH v2 05/12] vkd3d: Add simple pthread wrapper for MSVC. Message-Id: <20191001103349.7899-5-post@arntzen-software.no> Date: Tue, 1 Oct 2019 12:33:42 +0200 In-Reply-To: <20191001103349.7899-1-post@arntzen-software.no> References: <20190930141641.10431-1-post@arntzen-software.no> <20191001103349.7899-1-post@arntzen-software.no> Signed-off-by: Hans-Kristian Arntzen --- include/private/vkd3d_threads.h | 165 ++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 include/private/vkd3d_threads.h diff --git a/include/private/vkd3d_threads.h b/include/private/vkd3d_threads.h new file mode 100644 index 0000000..94d4307 --- /dev/null +++ b/include/private/vkd3d_threads.h @@ -0,0 +1,165 @@ +/* + * Copyright 2019 Hans-Kristian Arntzen for Valve + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __VKD3D_THREADS_H +#define __VKD3D_THREADS_H + +#include "config.h" + +#if defined(HAVE_PTHREAD_H) +#include + +#elif defined(_WIN32) /* HAVE_PTHREAD_H */ + +#define WIN32_LEAN_AND_MEAN +#include + +/* pthread_t is passed by value in some functions, + * which implies we need pthread_t to be a pointer type here. */ +struct pthread +{ + HANDLE thread; + DWORD id; + void * (*routine)(void *); + void *arg; +}; +typedef struct pthread *pthread_t; + +/* pthread_mutex_t is not copyable, so embed CS inline. */ +typedef struct pthread_mutex +{ + CRITICAL_SECTION lock; +} pthread_mutex_t; + +/* pthread_cond_t is not copyable, so embed CV inline. */ +typedef struct pthread_cond +{ + CONDITION_VARIABLE cond; +} pthread_cond_t; + +static DWORD WINAPI win32_thread_wrapper_routine(void *arg) +{ + pthread_t thread = arg; + thread->routine(thread->arg); + return 0; +} + +static inline int pthread_create(pthread_t *out_thread, void *attr, void * (*thread_fun)(void *), void *arg) +{ + pthread_t thread = vkd3d_calloc(1, sizeof(*thread)); + if (!thread) + return -1; + + (void)attr; + thread->routine = thread_fun; + thread->arg = arg; + thread->thread = CreateThread(NULL, 0, win32_thread_wrapper_routine, thread, 0, &thread->id); + if (!thread->thread) + { + vkd3d_free(thread); + return -1; + } + *out_thread = thread; + return 0; +} + +static inline int pthread_join(pthread_t thread, void **ret) +{ + (void)ret; + int success = WaitForSingleObject(thread->thread, INFINITE) == WAIT_OBJECT_0; + if (success) + { + CloseHandle(thread->thread); + vkd3d_free(thread); + } + return success ? 0 : -1; +} + +static inline int pthread_mutex_init(pthread_mutex_t *lock, void *attr) +{ + (void)attr; + InitializeCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_mutex_lock(pthread_mutex_t *lock) +{ + EnterCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_mutex_unlock(pthread_mutex_t *lock) +{ + LeaveCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_mutex_destroy(pthread_mutex_t *lock) +{ + DeleteCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_cond_init(pthread_cond_t *cond, void *attr) +{ + (void)attr; + InitializeConditionVariable(&cond->cond); + return 0; +} + +static inline void pthread_cond_destroy(pthread_cond_t *cond) +{ + (void)cond; +} + +static inline int pthread_cond_signal(pthread_cond_t *cond) +{ + WakeConditionVariable(&cond->cond); + return 0; +} + +static inline int pthread_cond_broadcast(pthread_cond_t *cond) +{ + WakeAllConditionVariable(&cond->cond); + return 0; +} + +static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *lock) +{ + bool ret = SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE); + return ret ? 0 : -1; +} + +#else /* HAVE_PTHREAD_H */ +#error "Threads are not supported. Cannot build." +#endif /* HAVE_PTHREAD_H */ + +static inline void vkd3d_set_thread_name(const char *name) +{ +#if defined(_MSC_VER) + (void)name; +#elif defined(HAVE_PTHREAD_SETNAME_NP_2) + pthread_setname_np(pthread_self(), name); +#elif defined(HAVE_PTHREAD_SETNAME_NP_1) + pthread_setname_np(name); +#else + (void)name; +#endif +} + +#endif /* __VKD3D_THREADS_H */ -- 2.23.0