Home | History | Annotate | Download | only in symbian
      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 (at) devolution.com
     21 */
     22 
     23 /*
     24     SDL_syssem.cpp
     25 
     26     Epoc version by Markus Mertama  (w (at) iki.fi)
     27 */
     28 
     29 #ifdef SAVE_RCSID
     30 static 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 
     46 struct SDL_semaphore
     47  {
     48  TInt handle;
     49  TInt count;
     50  };
     51 
     52 
     53 extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*);
     54 #ifndef EKA2
     55 extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2);
     56 #endif
     57 
     58 TInt 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 */
     65 SDL_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 */
     80 void 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 
    107 TBool 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 
    121 void _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 
    134 int 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 
    179 int SDL_SemTryWait(SDL_sem *sem)
    180 {
    181     if(sem->count > 0)
    182         {
    183         sem->count--;
    184         }
    185     return SDL_MUTEX_TIMEOUT;
    186 }
    187 
    188 int SDL_SemWait(SDL_sem *sem)
    189 {
    190 	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
    191 }
    192 
    193 /* Returns the current count of the semaphore */
    194 Uint32 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 
    203 int 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