1/* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 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/* 24 SDL_syssem.cpp 25 26 Epoc version by Markus Mertama (w@iki.fi) 27*/ 28 29#ifdef SAVE_RCSID 30static char rcsid = 31 "@(#) $Id: SDL_syssem.c,v 1.1.2.4 2000/06/22 15:24:48 hercules Exp $"; 32#endif 33 34/* Semaphore functions using the Win32 API */ 35 36//#include <stdio.h> 37//#include <stdlib.h> 38#include <e32std.h> 39 40#include "SDL_error.h" 41#include "SDL_thread.h" 42 43 44#define SDL_MUTEX_TIMEOUT -2 45 46struct SDL_semaphore 47 { 48 TInt handle; 49 TInt count; 50 }; 51 52 53extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*); 54#ifndef EKA2 55extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2); 56#endif 57 58TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2) 59 { 60 TInt value = *((TInt*) aPtr2); 61 return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value); 62 } 63 64/* Create a semaphore */ 65SDL_sem *SDL_CreateSemaphore(Uint32 initial_value) 66{ 67 RSemaphore s; 68 TInt status = CreateUnique(NewSema, &s, &initial_value); 69 if(status != KErrNone) 70 { 71 SDL_SetError("Couldn't create semaphore"); 72 } 73 SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore; 74 sem->handle = s.Handle(); 75 sem->count = initial_value; 76 return(sem); 77} 78 79/* Free the semaphore */ 80void SDL_DestroySemaphore(SDL_sem *sem) 81{ 82 if ( sem ) 83 { 84 RSemaphore sema; 85 sema.SetHandle(sem->handle); 86 while(--sem->count) 87 sema.Signal(); 88 sema.Close(); 89 delete sem; 90 sem = NULL; 91 } 92} 93 94#ifndef EKA2 95 96 struct TInfo 97 { 98 TInfo(TInt aTime, TInt aHandle) : 99 iTime(aTime), iHandle(aHandle), iVal(0) {} 100 TInt iTime; 101 TInt iHandle; 102 TInt iVal; 103 }; 104 105 106 107TBool ThreadRun(TAny* aInfo) 108 { 109 TInfo* info = STATIC_CAST(TInfo*, aInfo); 110 User::After(info->iTime); 111 RSemaphore sema; 112 sema.SetHandle(info->iHandle); 113 sema.Signal(); 114 info->iVal = SDL_MUTEX_TIMEOUT; 115 return 0; 116 } 117 118#endif 119 120 121void _WaitAll(SDL_sem *sem) 122 { 123 //since SemTryWait may changed the counter. 124 //this may not be atomic, but hopes it works. 125 RSemaphore sema; 126 sema.SetHandle(sem->handle); 127 sema.Wait(); 128 while(sem->count < 0) 129 { 130 sema.Wait(); 131 } 132 } 133 134int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout) 135{ 136 if ( ! sem ) { 137 SDL_SetError("Passed a NULL sem"); 138 return -1; 139 } 140 141 if ( timeout == SDL_MUTEX_MAXWAIT ) 142 { 143 _WaitAll(sem); 144 return SDL_MUTEX_MAXWAIT; 145 } 146 147#ifdef EKA2 148 149 RSemaphore sema; 150 sema.SetHandle(sem->handle); 151 if(KErrNone == sema.Wait(timeout)) 152 return 0; 153 return -1; 154#else 155 RThread thread; 156 157 TInfo* info = new (ELeave)TInfo(timeout, sem->handle); 158 159 TInt status = CreateUnique(NewThread, &thread, info); 160 161 if(status != KErrNone) 162 return status; 163 164 thread.Resume(); 165 166 _WaitAll(sem); 167 168 if(thread.ExitType() == EExitPending) 169 { 170 thread.Kill(SDL_MUTEX_TIMEOUT); 171 } 172 173 thread.Close(); 174 175 return info->iVal; 176#endif 177} 178 179int SDL_SemTryWait(SDL_sem *sem) 180{ 181 if(sem->count > 0) 182 { 183 sem->count--; 184 } 185 return SDL_MUTEX_TIMEOUT; 186} 187 188int SDL_SemWait(SDL_sem *sem) 189{ 190 return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT); 191} 192 193/* Returns the current count of the semaphore */ 194Uint32 SDL_SemValue(SDL_sem *sem) 195{ 196 if ( ! sem ) { 197 SDL_SetError("Passed a NULL sem"); 198 return 0; 199 } 200 return sem->count; 201} 202 203int SDL_SemPost(SDL_sem *sem) 204{ 205 if ( ! sem ) { 206 SDL_SetError("Passed a NULL sem"); 207 return -1; 208 } 209 sem->count++; 210 RSemaphore sema; 211 sema.SetHandle(sem->handle); 212 sema.Signal(); 213 return 0; 214} 215