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