]> git.saurik.com Git - wxWidgets.git/blob - src/palmos/thread.cpp
Fix for modal/modeless wizards
[wxWidgets.git] / src / palmos / thread.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/palmos/thread.cpp
3 // Purpose: wxThread Implementation
4 // Author: William Osborne - minimal working wxPalmOS port
5 // Modified by:
6 // Created: 10/13/04
7 // RCS-ID: $Id$
8 // Copyright: (c) William Osborne
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "thread.h"
14 #endif
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #if defined(__BORLANDC__)
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/intl.h"
29 #include "wx/app.h"
30 #endif
31
32 #if wxUSE_THREADS
33
34 #include "wx/apptrait.h"
35
36 #include "wx/palmos/private.h"
37 #include "wx/palmos/missing.h"
38
39 #include "wx/module.h"
40 #include "wx/thread.h"
41
42 // must have this symbol defined to get _beginthread/_endthread declarations
43 #ifndef _MT
44 #define _MT
45 #endif
46
47 #if defined(__BORLANDC__)
48 #if !defined(__MT__)
49 // I can't set -tWM in the IDE (anyone?) so have to do this
50 #define __MT__
51 #endif
52
53 #if !defined(__MFC_COMPAT__)
54 // Needed to know about _beginthreadex etc..
55 #define __MFC_COMPAT__
56 #endif
57 #endif // BC++
58
59 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function
60 // which should be used instead of Win32 ::CreateThread() if possible
61 #if defined(__VISUALC__) || \
62 (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \
63 (defined(__GNUG__) && defined(__MSVCRT__)) || \
64 defined(__WATCOMC__) || defined(__MWERKS__)
65
66 #ifndef __WXWINCE__
67 #undef wxUSE_BEGIN_THREAD
68 #define wxUSE_BEGIN_THREAD
69 #endif
70
71 #endif
72
73 #ifdef wxUSE_BEGIN_THREAD
74 // the return type of the thread function entry point
75 typedef unsigned THREAD_RETVAL;
76
77 // the calling convention of the thread function entry point
78 #define THREAD_CALLCONV __stdcall
79 #else
80 // the settings for CreateThread()
81 typedef DWORD THREAD_RETVAL;
82 #define THREAD_CALLCONV WINAPI
83 #endif
84
85 // ----------------------------------------------------------------------------
86 // constants
87 // ----------------------------------------------------------------------------
88
89 // the possible states of the thread ("=>" shows all possible transitions from
90 // this state)
91 enum wxThreadState
92 {
93 STATE_NEW, // didn't start execution yet (=> RUNNING)
94 STATE_RUNNING, // thread is running (=> PAUSED, CANCELED)
95 STATE_PAUSED, // thread is temporarily suspended (=> RUNNING)
96 STATE_CANCELED, // thread should terminate a.s.a.p. (=> EXITED)
97 STATE_EXITED // thread is terminating
98 };
99
100 // ----------------------------------------------------------------------------
101 // this module globals
102 // ----------------------------------------------------------------------------
103
104 // TLS index of the slot where we store the pointer to the current thread
105 static DWORD gs_tlsThisThread = 0xFFFFFFFF;
106
107 // id of the main thread - the one which can call GUI functions without first
108 // calling wxMutexGuiEnter()
109 static DWORD gs_idMainThread = 0;
110
111 // if it's false, some secondary thread is holding the GUI lock
112 static bool gs_bGuiOwnedByMainThread = true;
113
114 // critical section which controls access to all GUI functions: any secondary
115 // thread (i.e. except the main one) must enter this crit section before doing
116 // any GUI calls
117 static wxCriticalSection *gs_critsectGui = NULL;
118
119 // critical section which protects gs_nWaitingForGui variable
120 static wxCriticalSection *gs_critsectWaitingForGui = NULL;
121
122 // critical section which serializes WinThreadStart() and WaitForTerminate()
123 // (this is a potential bottleneck, we use a single crit sect for all threads
124 // in the system, but normally time spent inside it should be quite short)
125 static wxCriticalSection *gs_critsectThreadDelete = NULL;
126
127 // number of threads waiting for GUI in wxMutexGuiEnter()
128 static size_t gs_nWaitingForGui = 0;
129
130 // are we waiting for a thread termination?
131 static bool gs_waitingForThread = false;
132
133 // ============================================================================
134 // Windows implementation of thread and related classes
135 // ============================================================================
136
137 // ----------------------------------------------------------------------------
138 // wxCriticalSection
139 // ----------------------------------------------------------------------------
140
141 wxCriticalSection::wxCriticalSection()
142 {
143 }
144
145 wxCriticalSection::~wxCriticalSection()
146 {
147 }
148
149 void wxCriticalSection::Enter()
150 {
151 }
152
153 void wxCriticalSection::Leave()
154 {
155 }
156
157 // ----------------------------------------------------------------------------
158 // wxMutex
159 // ----------------------------------------------------------------------------
160
161 class wxMutexInternal
162 {
163 public:
164 wxMutexInternal(wxMutexType mutexType);
165 ~wxMutexInternal();
166
167 bool IsOk() const { return m_mutex != NULL; }
168
169 wxMutexError Lock() { return LockTimeout(INFINITE); }
170 wxMutexError TryLock() { return LockTimeout(0); }
171 wxMutexError Unlock();
172
173 private:
174 wxMutexError LockTimeout(DWORD milliseconds);
175
176 HANDLE m_mutex;
177
178 DECLARE_NO_COPY_CLASS(wxMutexInternal)
179 };
180
181 // all mutexes are recursive under Win32 so we don't use mutexType
182 wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
183 {
184 }
185
186 wxMutexInternal::~wxMutexInternal()
187 {
188 }
189
190 wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
191 {
192 return wxMUTEX_NO_ERROR;
193 }
194
195 wxMutexError wxMutexInternal::Unlock()
196 {
197 return wxMUTEX_NO_ERROR;
198 }
199
200 // --------------------------------------------------------------------------
201 // wxSemaphore
202 // --------------------------------------------------------------------------
203
204 // a trivial wrapper around Win32 semaphore
205 class wxSemaphoreInternal
206 {
207 public:
208 wxSemaphoreInternal(int initialcount, int maxcount);
209 ~wxSemaphoreInternal();
210
211 bool IsOk() const { return m_semaphore != NULL; }
212
213 wxSemaError Wait() { return WaitTimeout(INFINITE); }
214
215 wxSemaError TryWait()
216 {
217 wxSemaError rc = WaitTimeout(0);
218 if ( rc == wxSEMA_TIMEOUT )
219 rc = wxSEMA_BUSY;
220
221 return rc;
222 }
223
224 wxSemaError WaitTimeout(unsigned long milliseconds);
225
226 wxSemaError Post();
227
228 private:
229 HANDLE m_semaphore;
230
231 DECLARE_NO_COPY_CLASS(wxSemaphoreInternal)
232 };
233
234 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
235 {
236 }
237
238 wxSemaphoreInternal::~wxSemaphoreInternal()
239 {
240 }
241
242 wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
243 {
244 return wxSEMA_NO_ERROR;
245 }
246
247 wxSemaError wxSemaphoreInternal::Post()
248 {
249 return wxSEMA_NO_ERROR;
250 }
251
252 // ----------------------------------------------------------------------------
253 // wxThread implementation
254 // ----------------------------------------------------------------------------
255
256 // wxThreadInternal class
257 // ----------------------
258
259 class wxThreadInternal
260 {
261 public:
262 wxThreadInternal(wxThread *thread)
263 {
264 m_thread = thread;
265 m_hThread = 0;
266 m_state = STATE_NEW;
267 m_priority = WXTHREAD_DEFAULT_PRIORITY;
268 m_nRef = 1;
269 }
270
271 ~wxThreadInternal()
272 {
273 Free();
274 }
275
276 void Free()
277 {
278 if ( m_hThread )
279 {
280 if ( !::CloseHandle(m_hThread) )
281 {
282 wxLogLastError(wxT("CloseHandle(thread)"));
283 }
284
285 m_hThread = 0;
286 }
287 }
288
289 // create a new (suspended) thread (for the given thread object)
290 bool Create(wxThread *thread, unsigned int stackSize);
291
292 // wait for the thread to terminate, either by itself, or by asking it
293 // (politely, this is not Kill()!) to do it
294 wxThreadError WaitForTerminate(wxCriticalSection& cs,
295 wxThread::ExitCode *pRc,
296 wxThread *threadToDelete = NULL);
297
298 // kill the thread unconditionally
299 wxThreadError Kill();
300
301 // suspend/resume/terminate
302 bool Suspend();
303 bool Resume();
304 void Cancel() { m_state = STATE_CANCELED; }
305
306 // thread state
307 void SetState(wxThreadState state) { m_state = state; }
308 wxThreadState GetState() const { return m_state; }
309
310 // thread priority
311 void SetPriority(unsigned int priority);
312 unsigned int GetPriority() const { return m_priority; }
313
314 // thread handle and id
315 HANDLE GetHandle() const { return m_hThread; }
316 DWORD GetId() const { return m_tid; }
317
318 // thread function
319 static THREAD_RETVAL THREAD_CALLCONV WinThreadStart(void *thread);
320
321 void KeepAlive()
322 {
323 if ( m_thread->IsDetached() )
324 ::InterlockedIncrement(&m_nRef);
325 }
326
327 void LetDie()
328 {
329 if ( m_thread->IsDetached() && !::InterlockedDecrement(&m_nRef) )
330 delete m_thread;
331 }
332
333 private:
334 // the thread we're associated with
335 wxThread *m_thread;
336
337 HANDLE m_hThread; // handle of the thread
338 wxThreadState m_state; // state, see wxThreadState enum
339 unsigned int m_priority; // thread priority in "wx" units
340 DWORD m_tid; // thread id
341
342 // number of threads which need this thread to remain alive, when the count
343 // reaches 0 we kill the owning wxThread -- and die ourselves with it
344 LONG m_nRef;
345
346 DECLARE_NO_COPY_CLASS(wxThreadInternal)
347 };
348
349 // small class which keeps a thread alive during its lifetime
350 class wxThreadKeepAlive
351 {
352 public:
353 wxThreadKeepAlive(wxThreadInternal& thrImpl) : m_thrImpl(thrImpl)
354 { m_thrImpl.KeepAlive(); }
355 ~wxThreadKeepAlive()
356 { m_thrImpl.LetDie(); }
357
358 private:
359 wxThreadInternal& m_thrImpl;
360 };
361
362
363 THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
364 {
365 THREAD_RETVAL rc;
366
367 return rc;
368 }
369
370 void wxThreadInternal::SetPriority(unsigned int priority)
371 {
372 }
373
374 bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
375 {
376 return false;
377 }
378
379 wxThreadError wxThreadInternal::Kill()
380 {
381 return wxTHREAD_NO_ERROR;
382 }
383
384 wxThreadError
385 wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
386 wxThread::ExitCode *pRc,
387 wxThread *threadToDelete)
388 {
389 return wxTHREAD_NO_ERROR;
390 }
391
392 bool wxThreadInternal::Suspend()
393 {
394 return true;
395 }
396
397 bool wxThreadInternal::Resume()
398 {
399 return true;
400 }
401
402 // static functions
403 // ----------------
404
405 wxThread *wxThread::This()
406 {
407 return NULL;
408 }
409
410 bool wxThread::IsMain()
411 {
412 return true;
413 }
414
415 void wxThread::Yield()
416 {
417 }
418
419 void wxThread::Sleep(unsigned long milliseconds)
420 {
421 }
422
423 int wxThread::GetCPUCount()
424 {
425 return 1;
426 }
427
428 unsigned long wxThread::GetCurrentId()
429 {
430 return 0;
431 }
432
433 bool wxThread::SetConcurrency(size_t level)
434 {
435 return true;
436 }
437
438 // ctor and dtor
439 // -------------
440
441 wxThread::wxThread(wxThreadKind kind)
442 {
443 }
444
445 wxThread::~wxThread()
446 {
447 }
448
449 // create/start thread
450 // -------------------
451
452 wxThreadError wxThread::Create(unsigned int stackSize)
453 {
454 return wxTHREAD_NO_ERROR;
455 }
456
457 wxThreadError wxThread::Run()
458 {
459 return wxTHREAD_RUNNING;
460 }
461
462 // suspend/resume thread
463 // ---------------------
464
465 wxThreadError wxThread::Pause()
466 {
467 return wxTHREAD_NO_ERROR;
468 }
469
470 wxThreadError wxThread::Resume()
471 {
472 return wxTHREAD_NO_ERROR;
473 }
474
475 // stopping thread
476 // ---------------
477
478 wxThread::ExitCode wxThread::Wait()
479 {
480 return 0;
481 }
482
483 wxThreadError wxThread::Delete(ExitCode *pRc)
484 {
485 return wxTHREAD_NO_ERROR;
486 }
487
488 wxThreadError wxThread::Kill()
489 {
490 return wxTHREAD_NO_ERROR;
491 }
492
493 void wxThread::Exit(ExitCode status)
494 {
495 }
496
497 // priority setting
498 // ----------------
499
500 void wxThread::SetPriority(unsigned int prio)
501 {
502 }
503
504 unsigned int wxThread::GetPriority() const
505 {
506 return 1;
507 }
508
509 unsigned long wxThread::GetId() const
510 {
511 return 0;
512 }
513
514 bool wxThread::IsRunning() const
515 {
516 return true;
517 }
518
519 bool wxThread::IsAlive() const
520 {
521 return true;
522 }
523
524 bool wxThread::IsPaused() const
525 {
526 return false;
527 }
528
529 bool wxThread::TestDestroy()
530 {
531 return true;
532 }
533
534 // ----------------------------------------------------------------------------
535 // Automatic initialization for thread module
536 // ----------------------------------------------------------------------------
537
538 class wxThreadModule : public wxModule
539 {
540 public:
541 virtual bool OnInit();
542 virtual void OnExit();
543
544 private:
545 DECLARE_DYNAMIC_CLASS(wxThreadModule)
546 };
547
548 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
549
550 bool wxThreadModule::OnInit()
551 {
552 return true;
553 }
554
555 void wxThreadModule::OnExit()
556 {
557 }
558
559 // ----------------------------------------------------------------------------
560 // under Windows, these functions are implemented using a critical section and
561 // not a mutex, so the names are a bit confusing
562 // ----------------------------------------------------------------------------
563
564 void WXDLLIMPEXP_BASE wxMutexGuiEnter()
565 {
566 }
567
568 void WXDLLIMPEXP_BASE wxMutexGuiLeave()
569 {
570 }
571
572 void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
573 {
574 }
575
576 bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread()
577 {
578 return true;
579 }
580
581 // wake up the main thread if it's in ::GetMessage()
582 void WXDLLIMPEXP_BASE wxWakeUpMainThread()
583 {
584 }
585
586 bool WXDLLIMPEXP_BASE wxIsWaitingForThread()
587 {
588 return false;
589 }
590
591 // ----------------------------------------------------------------------------
592 // include common implementation code
593 // ----------------------------------------------------------------------------
594
595 #include "wx/thrimpl.cpp"
596
597 #endif // wxUSE_THREADS
598