Home | History | Annotate | Download | only in epoc
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 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     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 /*
     25     SDL_syssem.cpp
     26 
     27     Epoc version by Markus Mertama  (w (at) iki.fi)
     28 */
     29 
     30 /* Semaphore functions using the Win32 API */
     31 
     32 #include <e32std.h>
     33 
     34 #include "SDL_error.h"
     35 #include "SDL_thread.h"
     36 
     37 
     38 #define SDL_MUTEX_TIMEOUT -2
     39 
     40 struct SDL_semaphore
     41  {
     42  TInt handle;
     43  TInt count;
     44  };
     45 
     46 extern TInt CreateUnique(TInt (*aFunc)(const TDesC& aName, TAny*, TAny*), TAny*, TAny*);
     47 extern TInt NewThread(const TDesC& aName, TAny* aPtr1, TAny* aPtr2);
     48 
     49 TInt NewSema(const TDesC& aName, TAny* aPtr1, TAny* aPtr2)
     50     {
     51     TInt value = *((TInt*) aPtr2);
     52     return ((RSemaphore*)aPtr1)->CreateGlobal(aName, value);
     53     }
     54 
     55 /* Create a semaphore */
     56 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
     57 {
     58    RSemaphore s;
     59    TInt status = CreateUnique(NewSema, &s, &initial_value);
     60    if(status != KErrNone)
     61 	 {
     62 			SDL_SetError("Couldn't create semaphore");
     63 	}
     64     SDL_semaphore* sem = new /*(ELeave)*/ SDL_semaphore;
     65     sem->handle = s.Handle();
     66 	sem->count = initial_value;
     67 	return(sem);
     68 }
     69 
     70 /* Free the semaphore */
     71 void SDL_DestroySemaphore(SDL_sem *sem)
     72 {
     73 	if ( sem )
     74 	{
     75     RSemaphore sema;
     76     sema.SetHandle(sem->handle);
     77 	sema.Signal(sema.Count());
     78     sema.Close();
     79     delete sem;
     80 	sem = NULL;
     81 	}
     82 }
     83 
     84 
     85   struct TInfo
     86     {
     87         TInfo(TInt aTime, TInt aHandle) :
     88         iTime(aTime), iHandle(aHandle), iVal(0) {}
     89         TInt iTime;
     90         TInt iHandle;
     91         TInt iVal;
     92     };
     93 
     94 TBool ThreadRun(TAny* aInfo)
     95     {
     96         TInfo* info = STATIC_CAST(TInfo*, aInfo);
     97         User::After(info->iTime);
     98         RSemaphore sema;
     99         sema.SetHandle(info->iHandle);
    100         sema.Signal();
    101         info->iVal = SDL_MUTEX_TIMEOUT;
    102         return 0;
    103     }
    104 
    105 
    106 
    107 
    108 void _WaitAll(SDL_sem *sem)
    109     {
    110        //since SemTryWait may changed the counter.
    111        //this may not be atomic, but hopes it works.
    112     RSemaphore sema;
    113     sema.SetHandle(sem->handle);
    114     sema.Wait();
    115     while(sem->count < 0)
    116         {
    117         sema.Wait();
    118         }
    119     }
    120 
    121 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
    122 {
    123 	if ( ! sem ) {
    124 		SDL_SetError("Passed a NULL sem");
    125 		return -1;
    126 	}
    127 
    128 	if ( timeout == SDL_MUTEX_MAXWAIT )
    129 	    {
    130 	    _WaitAll(sem);
    131 		return SDL_MUTEX_MAXWAIT;
    132 	    }
    133 
    134 
    135 	RThread thread;
    136 
    137 	TInfo* info = new (ELeave)TInfo(timeout, sem->handle);
    138 
    139     TInt status = CreateUnique(NewThread, &thread, info);
    140 
    141 	if(status != KErrNone)
    142 	    return status;
    143 
    144 	thread.Resume();
    145 
    146 	_WaitAll(sem);
    147 
    148 	if(thread.ExitType() == EExitPending)
    149 	    {
    150 	        thread.Kill(SDL_MUTEX_TIMEOUT);
    151 	    }
    152 
    153 	thread.Close();
    154 
    155 	return info->iVal;
    156 }
    157 
    158 int SDL_SemTryWait(SDL_sem *sem)
    159 {
    160     if(sem->count > 0)
    161         {
    162         sem->count--;
    163         }
    164     return SDL_MUTEX_TIMEOUT;
    165 }
    166 
    167 int SDL_SemWait(SDL_sem *sem)
    168 {
    169 	return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
    170 }
    171 
    172 /* Returns the current count of the semaphore */
    173 Uint32 SDL_SemValue(SDL_sem *sem)
    174 {
    175 	if ( ! sem ) {
    176 		SDL_SetError("Passed a NULL sem");
    177 		return 0;
    178 	}
    179 	return sem->count;
    180 }
    181 
    182 int SDL_SemPost(SDL_sem *sem)
    183 {
    184 	if ( ! sem ) {
    185 		SDL_SetError("Passed a NULL sem");
    186 		return -1;
    187 	}
    188 	sem->count++;
    189     RSemaphore sema;
    190     sema.SetHandle(sem->handle);
    191 	sema.Signal();
    192 	return 0;
    193 }
    194