src/thread/generic/SDL_syssem.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SDL_CreateSemaphore
  2. SDL_DestroySemaphore
  3. SDL_SemTryWait
  4. SDL_SemWaitTimeout
  5. SDL_SemWait
  6. SDL_SemValue
  7. SDL_SemPost
  8. SDL_CreateSemaphore
  9. SDL_DestroySemaphore
  10. SDL_SemTryWait
  11. SDL_SemWaitTimeout
  12. SDL_SemWait
  13. SDL_SemValue
  14. SDL_SemPost

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_syssem.c,v 1.1.2.7 2001/02/10 07:20:04 hercules Exp $";
  26 #endif
  27 
  28 /* An implementation of semaphores using mutexes and condition variables */
  29 
  30 #include <stdlib.h>
  31 
  32 #include "SDL_error.h"
  33 #include "SDL_timer.h"
  34 #include "SDL_thread.h"
  35 #include "SDL_systhread_c.h"
  36 
  37 
  38 #ifdef DISABLE_THREADS
  39 
  40 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
     /* [<][>][^][v][top][bottom][index][help] */
  41 {
  42         SDL_SetError("SDL not configured with thread support");
  43         return (SDL_sem *)0;
  44 }
  45 
  46 void SDL_DestroySemaphore(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
  47 {
  48         return;
  49 }
  50 
  51 int SDL_SemTryWait(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
  52 {
  53         SDL_SetError("SDL not configured with thread support");
  54         return -1;
  55 }
  56 
  57 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
     /* [<][>][^][v][top][bottom][index][help] */
  58 {
  59         SDL_SetError("SDL not configured with thread support");
  60         return -1;
  61 }
  62 
  63 int SDL_SemWait(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         SDL_SetError("SDL not configured with thread support");
  66         return -1;
  67 }
  68 
  69 Uint32 SDL_SemValue(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71         return 0;
  72 }
  73 
  74 int SDL_SemPost(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76         SDL_SetError("SDL not configured with thread support");
  77         return -1;
  78 }
  79 
  80 #else
  81 
  82 struct SDL_semaphore
  83 {
  84         Uint32 count;
  85         Uint32 waiters_count;
  86         SDL_mutex *count_lock;
  87         SDL_cond *count_nonzero;
  88 };
  89 
  90 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92         SDL_sem *sem;
  93 
  94         sem = (SDL_sem *)malloc(sizeof(*sem));
  95         if ( ! sem ) {
  96                 SDL_OutOfMemory();
  97                 return(0);
  98         }
  99         sem->count = initial_value;
 100         sem->waiters_count = 0;
 101 
 102         sem->count_lock = SDL_CreateMutex();
 103         sem->count_nonzero = SDL_CreateCond();
 104         if ( ! sem->count_lock || ! sem->count_nonzero ) {
 105                 SDL_DestroySemaphore(sem);
 106                 return(0);
 107         }
 108 
 109         return(sem);
 110 }
 111 
 112 /* WARNING:
 113    You cannot call this function when another thread is using the semaphore.
 114 */
 115 void SDL_DestroySemaphore(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
 116 {
 117         if ( sem ) {
 118                 sem->count = 0xFFFFFFFF;
 119                 while ( sem->waiters_count > 0) {
 120                         SDL_CondSignal(sem->count_nonzero);
 121                         SDL_Delay(10);
 122                 }
 123                 SDL_DestroyCond(sem->count_nonzero);
 124                 SDL_mutexP(sem->count_lock);
 125                 SDL_mutexV(sem->count_lock);
 126                 SDL_DestroyMutex(sem->count_lock);
 127                 free(sem);
 128         }
 129 }
 130 
 131 int SDL_SemTryWait(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
 132 {
 133         int retval;
 134 
 135         if ( ! sem ) {
 136                 SDL_SetError("Passed a NULL semaphore");
 137                 return -1;
 138         }
 139 
 140         retval = SDL_MUTEX_TIMEDOUT;
 141         SDL_LockMutex(sem->count_lock);
 142         if ( sem->count > 0 ) {
 143                 --sem->count;
 144                 retval = 0;
 145         }
 146         SDL_UnlockMutex(sem->count_lock);
 147 
 148         return retval;
 149 }
 150 
 151 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
     /* [<][>][^][v][top][bottom][index][help] */
 152 {
 153         int retval;
 154 
 155         if ( ! sem ) {
 156                 SDL_SetError("Passed a NULL semaphore");
 157                 return -1;
 158         }
 159 
 160         /* A timeout of 0 is an easy case */
 161         if ( timeout == 0 ) {
 162                 return SDL_SemTryWait(sem);
 163         }
 164 
 165         SDL_LockMutex(sem->count_lock);
 166         ++sem->waiters_count;
 167         retval = 0;
 168         while ( (sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT) ) {
 169                 retval = SDL_CondWaitTimeout(sem->count_nonzero,
 170                                              sem->count_lock, timeout);
 171         }
 172         --sem->waiters_count;
 173         --sem->count;
 174         SDL_UnlockMutex(sem->count_lock);
 175 
 176         return retval;
 177 }
 178 
 179 int SDL_SemWait(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
 180 {
 181         return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
 182 }
 183 
 184 Uint32 SDL_SemValue(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186         Uint32 value;
 187         
 188         value = 0;
 189         if ( sem ) {
 190                 SDL_LockMutex(sem->count_lock);
 191                 value = sem->count;
 192                 SDL_UnlockMutex(sem->count_lock);
 193         }
 194         return value;
 195 }
 196 
 197 int SDL_SemPost(SDL_sem *sem)
     /* [<][>][^][v][top][bottom][index][help] */
 198 {
 199         if ( ! sem ) {
 200                 SDL_SetError("Passed a NULL semaphore");
 201                 return -1;
 202         }
 203 
 204         SDL_LockMutex(sem->count_lock);
 205         if ( sem->waiters_count > 0 ) {
 206                 SDL_CondSignal(sem->count_nonzero);
 207         }
 208         ++sem->count;
 209         SDL_UnlockMutex(sem->count_lock);
 210 
 211         return 0;
 212 }
 213 
 214 #endif /* DISABLE_THREADS */

/* [<][>][^][v][top][bottom][index][help] */