SDL-1.2.14
[sdl_omap.git] / src / thread / symbian / SDL_syssem.cpp
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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
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 }