SDL_syssem.c (4670B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23/* An implementation of semaphores using mutexes and condition variables */ 24 25#include "SDL_timer.h" 26#include "SDL_thread.h" 27#include "SDL_systhread_c.h" 28 29 30#if SDL_THREADS_DISABLED 31 32SDL_sem * 33SDL_CreateSemaphore(Uint32 initial_value) 34{ 35 SDL_SetError("SDL not built with thread support"); 36 return (SDL_sem *) 0; 37} 38 39void 40SDL_DestroySemaphore(SDL_sem * sem) 41{ 42} 43 44int 45SDL_SemTryWait(SDL_sem * sem) 46{ 47 return SDL_SetError("SDL not built with thread support"); 48} 49 50int 51SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) 52{ 53 return SDL_SetError("SDL not built with thread support"); 54} 55 56int 57SDL_SemWait(SDL_sem * sem) 58{ 59 return SDL_SetError("SDL not built with thread support"); 60} 61 62Uint32 63SDL_SemValue(SDL_sem * sem) 64{ 65 return 0; 66} 67 68int 69SDL_SemPost(SDL_sem * sem) 70{ 71 return SDL_SetError("SDL not built with thread support"); 72} 73 74#else 75 76struct SDL_semaphore 77{ 78 Uint32 count; 79 Uint32 waiters_count; 80 SDL_mutex *count_lock; 81 SDL_cond *count_nonzero; 82}; 83 84SDL_sem * 85SDL_CreateSemaphore(Uint32 initial_value) 86{ 87 SDL_sem *sem; 88 89 sem = (SDL_sem *) SDL_malloc(sizeof(*sem)); 90 if (!sem) { 91 SDL_OutOfMemory(); 92 return NULL; 93 } 94 sem->count = initial_value; 95 sem->waiters_count = 0; 96 97 sem->count_lock = SDL_CreateMutex(); 98 sem->count_nonzero = SDL_CreateCond(); 99 if (!sem->count_lock || !sem->count_nonzero) { 100 SDL_DestroySemaphore(sem); 101 return NULL; 102 } 103 104 return sem; 105} 106 107/* WARNING: 108 You cannot call this function when another thread is using the semaphore. 109*/ 110void 111SDL_DestroySemaphore(SDL_sem * sem) 112{ 113 if (sem) { 114 sem->count = 0xFFFFFFFF; 115 while (sem->waiters_count > 0) { 116 SDL_CondSignal(sem->count_nonzero); 117 SDL_Delay(10); 118 } 119 SDL_DestroyCond(sem->count_nonzero); 120 if (sem->count_lock) { 121 SDL_LockMutex(sem->count_lock); 122 SDL_UnlockMutex(sem->count_lock); 123 SDL_DestroyMutex(sem->count_lock); 124 } 125 SDL_free(sem); 126 } 127} 128 129int 130SDL_SemTryWait(SDL_sem * sem) 131{ 132 int retval; 133 134 if (!sem) { 135 return SDL_SetError("Passed a NULL semaphore"); 136 } 137 138 retval = SDL_MUTEX_TIMEDOUT; 139 SDL_LockMutex(sem->count_lock); 140 if (sem->count > 0) { 141 --sem->count; 142 retval = 0; 143 } 144 SDL_UnlockMutex(sem->count_lock); 145 146 return retval; 147} 148 149int 150SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout) 151{ 152 int retval; 153 154 if (!sem) { 155 return SDL_SetError("Passed a NULL semaphore"); 156 } 157 158 /* A timeout of 0 is an easy case */ 159 if (timeout == 0) { 160 return SDL_SemTryWait(sem); 161 } 162 163 SDL_LockMutex(sem->count_lock); 164 ++sem->waiters_count; 165 retval = 0; 166 while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) { 167 retval = SDL_CondWaitTimeout(sem->count_nonzero, 168 sem->count_lock, timeout); 169 } 170 --sem->waiters_count; 171 if (retval == 0) { 172 --sem->count; 173 } 174 SDL_UnlockMutex(sem->count_lock); 175 176 return retval; 177} 178 179int 180SDL_SemWait(SDL_sem * sem) 181{ 182 return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); 183} 184 185Uint32 186SDL_SemValue(SDL_sem * sem) 187{ 188 Uint32 value; 189 190 value = 0; 191 if (sem) { 192 SDL_LockMutex(sem->count_lock); 193 value = sem->count; 194 SDL_UnlockMutex(sem->count_lock); 195 } 196 return value; 197} 198 199int 200SDL_SemPost(SDL_sem * sem) 201{ 202 if (!sem) { 203 return SDL_SetError("Passed a NULL semaphore"); 204 } 205 206 SDL_LockMutex(sem->count_lock); 207 if (sem->waiters_count > 0) { 208 SDL_CondSignal(sem->count_nonzero); 209 } 210 ++sem->count; 211 SDL_UnlockMutex(sem->count_lock); 212 213 return 0; 214} 215 216#endif /* SDL_THREADS_DISABLED */ 217/* vi: set ts=4 sw=4 expandtab: */