cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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: */