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