e14743d1 |
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 | } |