sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_syssem.c (4670B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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 
     32 SDL_sem *
     33 SDL_CreateSemaphore(Uint32 initial_value)
     34 {
     35     SDL_SetError("SDL not built with thread support");
     36     return (SDL_sem *) 0;
     37 }
     38 
     39 void
     40 SDL_DestroySemaphore(SDL_sem * sem)
     41 {
     42 }
     43 
     44 int
     45 SDL_SemTryWait(SDL_sem * sem)
     46 {
     47     return SDL_SetError("SDL not built with thread support");
     48 }
     49 
     50 int
     51 SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
     52 {
     53     return SDL_SetError("SDL not built with thread support");
     54 }
     55 
     56 int
     57 SDL_SemWait(SDL_sem * sem)
     58 {
     59     return SDL_SetError("SDL not built with thread support");
     60 }
     61 
     62 Uint32
     63 SDL_SemValue(SDL_sem * sem)
     64 {
     65     return 0;
     66 }
     67 
     68 int
     69 SDL_SemPost(SDL_sem * sem)
     70 {
     71     return SDL_SetError("SDL not built with thread support");
     72 }
     73 
     74 #else
     75 
     76 struct SDL_semaphore
     77 {
     78     Uint32 count;
     79     Uint32 waiters_count;
     80     SDL_mutex *count_lock;
     81     SDL_cond *count_nonzero;
     82 };
     83 
     84 SDL_sem *
     85 SDL_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 */
    110 void
    111 SDL_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 
    129 int
    130 SDL_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 
    149 int
    150 SDL_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 
    179 int
    180 SDL_SemWait(SDL_sem * sem)
    181 {
    182     return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
    183 }
    184 
    185 Uint32
    186 SDL_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 
    199 int
    200 SDL_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: */