about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--meson.build74
-rw-r--r--src/windows/threads.h274
2 files changed, 334 insertions, 14 deletions
diff --git a/meson.build b/meson.build
index a8bd4ae..611408f 100644
--- a/meson.build
+++ b/meson.build
@@ -1,32 +1,78 @@
-project('Pong', 'c', license : 'GPL-3.0-only', version : '0.2', default_options : ['warning_level=3', 'werror=true', 'optimization=g', 'c_std=c11', 'prefix=/opt'])
-add_project_link_arguments('../raylib/libraylib.a', '-lm', '-ldl', '-lrt', language : 'c')
+project('Pong', 'c', license : 'GPL-3.0-only', version : '0.2', default_options : ['warning_level=3', 'werror=false', 'optimization=g', 'c_std=c11', 'prefix=/opt'])
 fs = import('fs')
 
+# Checks if on UNIX/POSIX System
+if host_machine.system() != 'windows'
+  if host_machine.system() != 'darwin'
+    set_variable('posix', true)
+  endif
+else
+  set_variable('posix', false)
+endif
+
+if get_variable('posix') == true
+  message('Cleaning raylib...')
+  # First clean up
+  run_command('make', '-C', 'raylib/src', 'clean', capture : true, check : true)
+  message('Building raylib...')
+  # Then Build
+  run_command('make', '-C', 'raylib/src', 'PLATFORM=PLATFORM_DESKTOP', 'RAYLIB_BUILD_MODE=RELEASE', capture : true, check : true)
+else
+  message('Cleaning raylib...')
+  # Have to put OS_PLATFORM=linux or makefile will complain about del command not being found.
+  run_command('mingw32-make', '-C', 'raylib/src', 'PLATFORM_OS=linux', 'clean', capture : true, check : true)
+  message('Building raylib...')
+  run_command('mingw32-make', '-C', 'raylib/src', 'PLATFORM=PLATFORM_DESKTOP', 'RAYLIB_BUILD_MODE=RELEASE', capture : true, check : true)
+endif
 
-message('Cleaning raylib...')
-# First clean up
-run_command('make', '-C', 'raylib/src', 'clean', capture : true, check : true)
-message('Building raylib...')
-# Then Build
-run_command('make', '-C', 'raylib/src', 'PLATFORM=PLATFORM_DESKTOP', 'RAYLIB_BUILD_MODE=RELEASE', capture : true, check : true)
+# Find the static library
 if fs.exists('raylib/libraylib.a') == true
-    message('raylib successfully compiled.')
+    add_project_link_arguments('../raylib/libraylib.a', language : 'c')
+elif fs.exists('raylib/src/libraylib.a') == true
+    add_project_link_arguments('../raylib/src/libraylib.a', language : 'c')
 else
     error('raylib failed to compile. Check meson-logs to see what went wrong.')
 endif
 
-Raylib_Include = include_directories('raylib/src')
+message('raylib successfully compiled.')
+
+Include_Directories = include_directories('raylib/src')
 
 # Install launcher if flatpak
 if get_option('build_flatpak') == true
     install_data('src/launch.sh', install_dir : 'bin')
 endif
 
-X11_Dep = dependency('x11')
-Threads_Dep = dependency('threads')
+# Checks if on UNIX/POSIX System
+if host_machine.system() != 'windows'
+  if host_machine.system() != 'darwin'
+    set_variable('posix', true)
+  endif
+else
+  set_variable('posix', false)
+endif
+
+if get_variable('posix') == true
+  X11_Dep = dependency('x11')
+endif
+
 GL_Dep = dependency('gl')
+Threads_Dep = dependency('threads')
 
 Sources = ['src/main.c', 'src/enemy.c', 'src/ball.c', 'src/title.c', 'src/versus.c', 'src/marathon.c']
 
-executable('pong', Sources, dependencies : [X11_Dep, Threads_Dep, GL_Dep], install : true, install_dir : 'Pong', include_directories : Raylib_Include)
-install_subdir('resources', install_dir : 'Pong')
\ No newline at end of file
+if get_variable('posix') == true
+  Dependencies = [GL_Dep, Threads_Dep, X11_Dep]
+  add_project_link_arguments('-lGL', '-lm', '-lpthread', '-ldl', '-lrt', '-lX11', language : 'c')
+else
+  Dependencies = [GL_Dep, Threads_Dep]
+  add_project_link_arguments('-lopengl32', '-lgdi32', '-lwinmm', '-lpthread', '-lm', language : 'c')
+endif
+
+# If on windows, we need the c11 threads emulation layer.
+if get_variable('posix') == false
+  Include_Directories = include_directories(['raylib/src', 'src/windows'])
+endif
+
+executable('pong', Sources, dependencies : Dependencies, install : true, install_dir : 'Pong', include_directories : Include_Directories)
+install_subdir('resources', install_dir : 'Pong')
diff --git a/src/windows/threads.h b/src/windows/threads.h
new file mode 100644
index 0000000..7be02e5
--- /dev/null
+++ b/src/windows/threads.h
@@ -0,0 +1,274 @@
+/*
+Author: John Tsiombikas <nuclear@member.fsf.org>
+
+I place this piece of code in the public domain. Feel free to use as you see
+fit.  I'd appreciate it if you keep my name at the top of the code somehwere,
+but whatever.
+
+Main project site: https://github.com/jtsiomb/c11threads
+*/
+
+#ifndef C11THREADS_H_
+#define C11THREADS_H_
+
+#include <time.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>	/* for sched_yield */
+#include <sys/time.h>
+
+#define thread_local	_Thread_local
+#define ONCE_FLAG_INIT	PTHREAD_ONCE_INIT
+
+#ifdef __APPLE__
+/* Darwin doesn't implement timed mutexes currently */
+#define C11THREADS_NO_TIMED_MUTEX
+#endif
+
+#ifdef C11THREADS_NO_TIMED_MUTEX
+#define PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_NORMAL
+#define C11THREADS_TIMEDLOCK_POLL_INTERVAL 5000000	/* 5 ms */
+#endif
+
+/* types */
+typedef pthread_t thrd_t;
+typedef pthread_mutex_t mtx_t;
+typedef pthread_cond_t cnd_t;
+typedef pthread_key_t tss_t;
+typedef pthread_once_t once_flag;
+
+typedef int (*thrd_start_t)(void*);
+typedef void (*tss_dtor_t)(void*);
+
+enum {
+	mtx_plain		= 0,
+	mtx_recursive	= 1,
+	mtx_timed		= 2,
+};
+
+enum {
+	thrd_success,
+	thrd_timedout,
+	thrd_busy,
+	thrd_error,
+	thrd_nomem
+};
+
+
+/* ---- thread management ---- */
+
+static inline int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
+{
+	int res = pthread_create(thr, 0, (void*(*)(void*))func, arg);
+	if(res == 0) {
+		return thrd_success;
+	}
+	return res == ENOMEM ? thrd_nomem : thrd_error;
+}
+
+static inline void thrd_exit(int res)
+{
+	pthread_exit((void*)(long)res);
+}
+
+static inline int thrd_join(thrd_t thr, int *res)
+{
+	void *retval;
+
+	if(pthread_join(thr, &retval) != 0) {
+		return thrd_error;
+	}
+	if(res) {
+		*res = (int)(long)retval;
+	}
+	return thrd_success;
+}
+
+static inline int thrd_detach(thrd_t thr)
+{
+	return pthread_detach(thr) == 0 ? thrd_success : thrd_error;
+}
+
+static inline thrd_t thrd_current(void)
+{
+	return pthread_self();
+}
+
+static inline int thrd_equal(thrd_t a, thrd_t b)
+{
+	return pthread_equal(a, b);
+}
+
+static inline int thrd_sleep(const struct timespec *ts_in, struct timespec *rem_out)
+{
+	if(nanosleep(ts_in, rem_out) < 0) {
+		if(errno == EINTR) return -1;
+		return -2;
+	}
+	return 0;
+}
+
+static inline void thrd_yield(void)
+{
+	sched_yield();
+}
+
+/* ---- mutexes ---- */
+
+static inline int mtx_init(mtx_t *mtx, int type)
+{
+	int res;
+	pthread_mutexattr_t attr;
+
+	pthread_mutexattr_init(&attr);
+
+	if(type & mtx_timed) {
+		pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP);
+	}
+	if(type & mtx_recursive) {
+		pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+	}
+
+	res = pthread_mutex_init(mtx, &attr) == 0 ? thrd_success : thrd_error;
+	pthread_mutexattr_destroy(&attr);
+	return res;
+}
+
+static inline void mtx_destroy(mtx_t *mtx)
+{
+	pthread_mutex_destroy(mtx);
+}
+
+static inline int mtx_lock(mtx_t *mtx)
+{
+	int res = pthread_mutex_lock(mtx);
+	if(res == EDEADLK) {
+		return thrd_busy;
+	}
+	return res == 0 ? thrd_success : thrd_error;
+}
+
+static inline int mtx_trylock(mtx_t *mtx)
+{
+	int res = pthread_mutex_trylock(mtx);
+	if(res == EBUSY) {
+		return thrd_busy;
+	}
+	return res == 0 ? thrd_success : thrd_error;
+}
+
+static inline int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
+{
+	int res;
+#ifdef C11THREADS_NO_TIMED_MUTEX
+	/* fake a timedlock by polling trylock in a loop and waiting for a bit */
+	struct timeval now;
+	struct timespec sleeptime;
+
+	sleeptime.tv_sec = 0;
+	sleeptime.tv_nsec = C11THREADS_TIMEDLOCK_POLL_INTERVAL;
+
+	while((res = pthread_mutex_trylock(mtx)) == EBUSY) {
+		gettimeofday(&now, NULL);
+
+		if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec &&
+					(now.tv_usec * 1000) >= ts->tv_nsec)) {
+			return thrd_timedout;
+		}
+
+		nanosleep(&sleeptime, NULL);
+	}
+#else
+	if((res = pthread_mutex_timedlock(mtx, ts)) == ETIMEDOUT) {
+		return thrd_timedout;
+	}
+#endif
+	return res == 0 ? thrd_success : thrd_error;
+}
+
+static inline int mtx_unlock(mtx_t *mtx)
+{
+	return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;
+}
+
+/* ---- condition variables ---- */
+
+static inline int cnd_init(cnd_t *cond)
+{
+	return pthread_cond_init(cond, 0) == 0 ? thrd_success : thrd_error;
+}
+
+static inline void cnd_destroy(cnd_t *cond)
+{
+	pthread_cond_destroy(cond);
+}
+
+static inline int cnd_signal(cnd_t *cond)
+{
+	return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+}
+
+static inline int cnd_broadcast(cnd_t *cond)
+{
+	return pthread_cond_broadcast(cond) == 0 ? thrd_success : thrd_error;
+}
+
+static inline int cnd_wait(cnd_t *cond, mtx_t *mtx)
+{
+	return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
+}
+
+static inline int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
+{
+	int res;
+
+	if((res = pthread_cond_timedwait(cond, mtx, ts)) != 0) {
+		return res == ETIMEDOUT ? thrd_timedout : thrd_error;
+	}
+	return thrd_success;
+}
+
+/* ---- thread-specific data ---- */
+
+static inline int tss_create(tss_t *key, tss_dtor_t dtor)
+{
+	return pthread_key_create(key, dtor) == 0 ? thrd_success : thrd_error;
+}
+
+static inline void tss_delete(tss_t key)
+{
+	pthread_key_delete(key);
+}
+
+static inline int tss_set(tss_t key, void *val)
+{
+	return pthread_setspecific(key, val) == 0 ? thrd_success : thrd_error;
+}
+
+static inline void *tss_get(tss_t key)
+{
+	return pthread_getspecific(key);
+}
+
+/* ---- misc ---- */
+
+static inline void call_once(once_flag *flag, void (*func)(void))
+{
+	pthread_once(flag, func);
+}
+
+#if __STDC_VERSION__ < 201112L || defined(C11THREADS_NO_TIMED_MUTEX)
+/* TODO take base into account */
+static inline int timespec_get(struct timespec *ts, int base)
+{
+	struct timeval tv;
+
+	gettimeofday(&tv, 0);
+
+	ts->tv_sec = tv.tv_sec;
+	ts->tv_nsec = tv.tv_usec * 1000;
+	return base;
+}
+#endif	/* not C11 */
+
+#endif	/* C11THREADS_H_ */