1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * SDL thread support.
12 *
13 * See LICENSE.txt for copyright information.
14 */
15 #include "allegro5/allegro.h"
16 #include "allegro5/internal/aintern.h"
17 #include "allegro5/internal/aintern_thread.h"
18 #include "allegro5/platform/allegro_internal_sdl.h"
19
20 ALLEGRO_DEBUG_CHANNEL("thread")
21
thread_trampoline(void * data)22 static int thread_trampoline(void* data)
23 {
24 _AL_THREAD *thread = data;
25 (*thread->proc)(thread, thread->arg);
26 return 0;
27 }
28
_al_thread_create(_AL_THREAD * thread,void (* proc)(_AL_THREAD *,void *),void * arg)29 void _al_thread_create(_AL_THREAD *thread, void (*proc)(_AL_THREAD*, void*),
30 void *arg)
31 {
32 ASSERT(thread);
33 ASSERT(proc);
34 thread->should_stop = false;
35 thread->proc = proc;
36 thread->arg = arg;
37 thread->thread = SDL_CreateThread(thread_trampoline, "allegro", thread);
38 }
39
_al_thread_create_with_stacksize(_AL_THREAD * thread,void (* proc)(_AL_THREAD *,void *),void * arg,size_t stacksize)40 void _al_thread_create_with_stacksize(_AL_THREAD *thread, void (*proc)(_AL_THREAD*, void*),
41 void *arg, size_t stacksize)
42 {
43 ASSERT(thread);
44 ASSERT(proc);
45 thread->should_stop = false;
46 thread->proc = proc;
47 thread->arg = arg;
48 #if SDL_VERSION_ATLEAST(2,0,9)
49 thread->thread = SDL_CreateThreadWithStackSize(thread_trampoline, "allegro", stacksize, thread);
50 #else
51 (void)stacksize;
52 ALLEGRO_WARN("Creating a thread with a custom thread size is not supported "
53 "on this version of SDL, it is too old.\n");
54 thread->thread = SDL_CreateThread(thread_trampoline, "allegro", thread);
55 #endif
56 }
57
_al_thread_set_should_stop(_AL_THREAD * thread)58 void _al_thread_set_should_stop(_AL_THREAD *thread)
59 {
60 ASSERT(thread);
61 thread->should_stop = true;
62 }
63
_al_thread_join(_AL_THREAD * thread)64 void _al_thread_join(_AL_THREAD *thread)
65 {
66 ASSERT(thread);
67 _al_thread_set_should_stop(thread);
68 int r;
69 SDL_WaitThread(thread->thread, &r);
70 }
71
_al_thread_detach(_AL_THREAD * thread)72 void _al_thread_detach(_AL_THREAD *thread)
73 {
74 ASSERT(thread);
75 SDL_DetachThread(thread->thread);
76 }
77
78 /* mutexes */
79
_al_mutex_init(_AL_MUTEX * mutex)80 void _al_mutex_init(_AL_MUTEX *mutex)
81 {
82 ASSERT(mutex);
83
84 mutex->mutex = SDL_CreateMutex();
85 }
86
_al_mutex_init_recursive(_AL_MUTEX * mutex)87 void _al_mutex_init_recursive(_AL_MUTEX *mutex)
88 {
89 _al_mutex_init(mutex);
90 }
91
_al_mutex_destroy(_AL_MUTEX * mutex)92 void _al_mutex_destroy(_AL_MUTEX *mutex)
93 {
94 ASSERT(mutex);
95
96 if (mutex->mutex) {
97 SDL_DestroyMutex(mutex->mutex);
98 mutex->mutex = NULL;
99 }
100 }
101
102 /* condition variables */
103 /* most of the condition variable implementation is actually inline */
104
_al_cond_timedwait(_AL_COND * cond,_AL_MUTEX * mutex,const ALLEGRO_TIMEOUT * timeout)105 int _al_cond_timedwait(_AL_COND *cond, _AL_MUTEX *mutex,
106 const ALLEGRO_TIMEOUT *timeout)
107 {
108 ALLEGRO_TIMEOUT_SDL *timeout_sdl = (void *)timeout;
109 int r = SDL_CondWaitTimeout(cond->cond, mutex->mutex, timeout_sdl->ms);
110
111 return (r == SDL_MUTEX_TIMEDOUT) ? -1 : 0;
112 }
113