Mercurial > sdl-ios-xcode
comparison src/events/SDL_events.c @ 5125:dc0dfdd58f27
Removed completely non-portable event thread hack.
Next I'll be working on generalizing the event sources and making the event queue lock-free. :)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 27 Jan 2011 22:44:08 -0800 |
parents | 481dabb098ef |
children | 3052772b59db |
comparison
equal
deleted
inserted
replaced
5124:0ec550f04bbc | 5125:dc0dfdd58f27 |
---|---|
25 | 25 |
26 #include "SDL.h" | 26 #include "SDL.h" |
27 #include "SDL_events.h" | 27 #include "SDL_events.h" |
28 #include "SDL_syswm.h" | 28 #include "SDL_syswm.h" |
29 #include "SDL_thread.h" | 29 #include "SDL_thread.h" |
30 #include "SDL_sysevents.h" | |
31 #include "SDL_events_c.h" | 30 #include "SDL_events_c.h" |
32 #include "../timer/SDL_timer_c.h" | 31 #include "../timer/SDL_timer_c.h" |
33 #if !SDL_JOYSTICK_DISABLED | 32 #if !SDL_JOYSTICK_DISABLED |
34 #include "../joystick/SDL_joystick_c.h" | 33 #include "../joystick/SDL_joystick_c.h" |
35 #endif | 34 #endif |
35 #include "../video/SDL_sysvideo.h" | |
36 | 36 |
37 /* Public data -- the event filter */ | 37 /* Public data -- the event filter */ |
38 SDL_EventFilter SDL_EventOK = NULL; | 38 SDL_EventFilter SDL_EventOK = NULL; |
39 void *SDL_EventOKParam; | 39 void *SDL_EventOKParam; |
40 | 40 |
56 SDL_Event event[MAXEVENTS]; | 56 SDL_Event event[MAXEVENTS]; |
57 int wmmsg_next; | 57 int wmmsg_next; |
58 struct SDL_SysWMmsg wmmsg[MAXEVENTS]; | 58 struct SDL_SysWMmsg wmmsg[MAXEVENTS]; |
59 } SDL_EventQ; | 59 } SDL_EventQ; |
60 | 60 |
61 /* Private data -- event locking structure */ | |
62 static struct | |
63 { | |
64 SDL_mutex *lock; | |
65 int safe; | |
66 } SDL_EventLock; | |
67 | |
68 /* Thread functions */ | |
69 static SDL_Thread *SDL_EventThread = NULL; /* Thread handle */ | |
70 static SDL_threadID event_thread; /* The event thread id */ | |
71 | |
72 void | |
73 SDL_Lock_EventThread(void) | |
74 { | |
75 if (SDL_EventThread && (SDL_ThreadID() != event_thread)) { | |
76 /* Grab lock and spin until we're sure event thread stopped */ | |
77 SDL_mutexP(SDL_EventLock.lock); | |
78 while (!SDL_EventLock.safe) { | |
79 SDL_Delay(1); | |
80 } | |
81 } | |
82 } | |
83 | |
84 void | |
85 SDL_Unlock_EventThread(void) | |
86 { | |
87 if (SDL_EventThread && (SDL_ThreadID() != event_thread)) { | |
88 SDL_mutexV(SDL_EventLock.lock); | |
89 } | |
90 } | |
91 | 61 |
92 static __inline__ SDL_bool | 62 static __inline__ SDL_bool |
93 SDL_ShouldPollJoystick() | 63 SDL_ShouldPollJoystick() |
94 { | 64 { |
95 #if !SDL_JOYSTICK_DISABLED | 65 #if !SDL_JOYSTICK_DISABLED |
100 } | 70 } |
101 #endif | 71 #endif |
102 return SDL_FALSE; | 72 return SDL_FALSE; |
103 } | 73 } |
104 | 74 |
105 static int SDLCALL | 75 /* Public functions */ |
106 SDL_GobbleEvents(void *unused) | 76 |
107 { | 77 void |
108 event_thread = SDL_ThreadID(); | 78 SDL_StopEventLoop(void) |
109 | 79 { |
110 while (SDL_EventQ.active) { | 80 int i; |
111 SDL_VideoDevice *_this = SDL_GetVideoDevice(); | 81 |
112 | 82 if (SDL_EventQ.lock) { |
113 /* Get events from the video subsystem */ | 83 SDL_DestroyMutex(SDL_EventQ.lock); |
114 if (_this) { | 84 SDL_EventQ.lock = NULL; |
115 _this->PumpEvents(_this); | 85 } |
116 } | 86 |
117 #if !SDL_JOYSTICK_DISABLED | 87 /* Clean out EventQ */ |
118 /* Check for joystick state change */ | 88 SDL_EventQ.head = 0; |
119 if (SDL_ShouldPollJoystick()) { | 89 SDL_EventQ.tail = 0; |
120 SDL_JoystickUpdate(); | 90 SDL_EventQ.wmmsg_next = 0; |
121 } | 91 |
122 #endif | 92 /* Clear disabled event state */ |
123 | 93 for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) { |
124 /* Give up the CPU for the rest of our timeslice */ | 94 if (SDL_disabled_events[i]) { |
125 SDL_EventLock.safe = 1; | 95 SDL_free(SDL_disabled_events[i]); |
126 SDL_Delay(1); | 96 SDL_disabled_events[i] = NULL; |
127 | 97 } |
128 /* Check for event locking. | 98 } |
129 On the P of the lock mutex, if the lock is held, this thread | 99 } |
130 will wait until the lock is released before continuing. The | 100 |
131 safe flag will be set, meaning that the other thread can go | 101 /* This function (and associated calls) may be called more than once */ |
132 about it's business. The safe flag is reset before the V, | 102 int |
133 so as soon as the mutex is free, other threads can see that | 103 SDL_StartEventLoop(void) |
134 it's not safe to interfere with the event thread. | 104 { |
135 */ | 105 int retcode; |
136 SDL_mutexP(SDL_EventLock.lock); | 106 |
137 SDL_EventLock.safe = 0; | 107 /* Clean out the event queue */ |
138 SDL_mutexV(SDL_EventLock.lock); | 108 SDL_EventQ.lock = NULL; |
139 } | 109 SDL_StopEventLoop(); |
140 event_thread = 0; | 110 |
141 return (0); | 111 /* No filter to start with, process most event types */ |
142 } | 112 SDL_EventOK = NULL; |
143 | 113 SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE); |
144 static int | |
145 SDL_StartEventThread(Uint32 flags) | |
146 { | |
147 /* Reset everything to zero */ | |
148 SDL_EventThread = NULL; | |
149 SDL_memset(&SDL_EventLock, 0, sizeof(SDL_EventLock)); | |
150 | 114 |
151 /* Create the lock and set ourselves active */ | 115 /* Create the lock and set ourselves active */ |
152 #if !SDL_THREADS_DISABLED | 116 #if !SDL_THREADS_DISABLED |
153 SDL_EventQ.lock = SDL_CreateMutex(); | 117 SDL_EventQ.lock = SDL_CreateMutex(); |
154 if (SDL_EventQ.lock == NULL) { | 118 if (SDL_EventQ.lock == NULL) { |
155 return (-1); | 119 return (-1); |
156 } | 120 } |
157 #endif /* !SDL_THREADS_DISABLED */ | 121 #endif /* !SDL_THREADS_DISABLED */ |
158 SDL_EventQ.active = 1; | 122 SDL_EventQ.active = 1; |
159 | 123 |
160 if ((flags & SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD) { | |
161 SDL_EventLock.lock = SDL_CreateMutex(); | |
162 if (SDL_EventLock.lock == NULL) { | |
163 return (-1); | |
164 } | |
165 SDL_EventLock.safe = 0; | |
166 | |
167 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) | |
168 #undef SDL_CreateThread | |
169 SDL_EventThread = | |
170 SDL_CreateThread(SDL_GobbleEvents, NULL, NULL, NULL); | |
171 #else | |
172 SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL); | |
173 #endif | |
174 if (SDL_EventThread == NULL) { | |
175 return (-1); | |
176 } | |
177 } else { | |
178 event_thread = 0; | |
179 } | |
180 return (0); | |
181 } | |
182 | |
183 static void | |
184 SDL_StopEventThread(void) | |
185 { | |
186 SDL_EventQ.active = 0; | |
187 if (SDL_EventThread) { | |
188 SDL_WaitThread(SDL_EventThread, NULL); | |
189 SDL_EventThread = NULL; | |
190 SDL_DestroyMutex(SDL_EventLock.lock); | |
191 SDL_EventLock.lock = NULL; | |
192 } | |
193 if (SDL_EventQ.lock) { | |
194 SDL_DestroyMutex(SDL_EventQ.lock); | |
195 SDL_EventQ.lock = NULL; | |
196 } | |
197 } | |
198 | |
199 SDL_threadID | |
200 SDL_EventThreadID(void) | |
201 { | |
202 return (event_thread); | |
203 } | |
204 | |
205 /* Public functions */ | |
206 | |
207 void | |
208 SDL_StopEventLoop(void) | |
209 { | |
210 int i; | |
211 | |
212 /* Halt the event thread, if running */ | |
213 SDL_StopEventThread(); | |
214 | |
215 /* Shutdown event handlers */ | |
216 SDL_KeyboardQuit(); | |
217 SDL_MouseQuit(); | |
218 SDL_QuitQuit(); | |
219 | |
220 /* Clean out EventQ */ | |
221 SDL_EventQ.head = 0; | |
222 SDL_EventQ.tail = 0; | |
223 SDL_EventQ.wmmsg_next = 0; | |
224 | |
225 /* Clear disabled event state */ | |
226 for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) { | |
227 if (SDL_disabled_events[i]) { | |
228 SDL_free(SDL_disabled_events[i]); | |
229 SDL_disabled_events[i] = NULL; | |
230 } | |
231 } | |
232 } | |
233 | |
234 /* This function (and associated calls) may be called more than once */ | |
235 int | |
236 SDL_StartEventLoop(Uint32 flags) | |
237 { | |
238 int retcode; | |
239 | |
240 /* Clean out the event queue */ | |
241 SDL_EventThread = NULL; | |
242 SDL_EventQ.lock = NULL; | |
243 SDL_StopEventLoop(); | |
244 | |
245 /* No filter to start with, process most event types */ | |
246 SDL_EventOK = NULL; | |
247 SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE); | |
248 | |
249 /* Initialize event handlers */ | |
250 retcode = 0; | |
251 retcode += SDL_KeyboardInit(); | |
252 retcode += SDL_MouseInit(); | |
253 retcode += SDL_TouchInit(); | |
254 retcode += SDL_QuitInit(); | |
255 if (retcode < 0) { | |
256 /* We don't expect them to fail, but... */ | |
257 return (-1); | |
258 } | |
259 | |
260 /* Create the lock and event thread */ | |
261 if (SDL_StartEventThread(flags) < 0) { | |
262 SDL_StopEventLoop(); | |
263 return (-1); | |
264 } | |
265 return (0); | 124 return (0); |
266 } | 125 } |
267 | 126 |
268 | 127 |
269 /* Add an event to the event queue -- called with the queue locked */ | 128 /* Add an event to the event queue -- called with the queue locked */ |
418 | 277 |
419 /* Run the system dependent event loops */ | 278 /* Run the system dependent event loops */ |
420 void | 279 void |
421 SDL_PumpEvents(void) | 280 SDL_PumpEvents(void) |
422 { | 281 { |
423 if (!SDL_EventThread) { | 282 SDL_VideoDevice *_this = SDL_GetVideoDevice(); |
424 SDL_VideoDevice *_this = SDL_GetVideoDevice(); | 283 |
425 | 284 /* Get events from the video subsystem */ |
426 /* Get events from the video subsystem */ | 285 if (_this) { |
427 if (_this) { | 286 _this->PumpEvents(_this); |
428 _this->PumpEvents(_this); | 287 } |
429 } | |
430 #if !SDL_JOYSTICK_DISABLED | 288 #if !SDL_JOYSTICK_DISABLED |
431 /* Check for joystick state change */ | 289 /* Check for joystick state change */ |
432 if (SDL_ShouldPollJoystick()) { | 290 if (SDL_ShouldPollJoystick()) { |
433 SDL_JoystickUpdate(); | 291 SDL_JoystickUpdate(); |
434 } | 292 } |
435 #endif | 293 #endif |
436 } | |
437 } | 294 } |
438 | 295 |
439 /* Public functions */ | 296 /* Public functions */ |
440 | 297 |
441 int | 298 int |