• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@libsdl.org
21 */
22 #include "SDL_config.h"
23 
24 /*
25     SDL_syssem.cpp
26 
27     Epoc version by Markus Mertama  (w@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 
NewSema(const TDesC & aName,TAny * aPtr1,TAny * aPtr2)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 */
SDL_CreateSemaphore(Uint32 initial_value)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 */
SDL_DestroySemaphore(SDL_sem * sem)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     {
TInfoTInfo87         TInfo(TInt aTime, TInt aHandle) :
88         iTime(aTime), iHandle(aHandle), iVal(0) {}
89         TInt iTime;
90         TInt iHandle;
91         TInt iVal;
92     };
93 
ThreadRun(TAny * aInfo)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 
_WaitAll(SDL_sem * sem)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 
SDL_SemWaitTimeout(SDL_sem * sem,Uint32 timeout)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 
SDL_SemTryWait(SDL_sem * sem)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 
SDL_SemWait(SDL_sem * sem)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 */
SDL_SemValue(SDL_sem * sem)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 
SDL_SemPost(SDL_sem * sem)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