]> git.saurik.com Git - wxWidgets.git/blob - src/msw/thread.cpp
ensure that one of wxRA_SPECIFY_{COLS,ROWS} is set in the radiobox style, otherwise...
[wxWidgets.git] / src / msw / thread.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/thread.cpp
3 // Purpose: wxThread Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
5 // Modified by: Vadim Zeitlin to make it work :-)
6 // Created: 04/22/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Wolfram Gloger (1996, 1997), Guilhem Lavaux (1998);
9 // Vadim Zeitlin (1999-2002)
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ----------------------------------------------------------------------------
14 // headers
15 // ----------------------------------------------------------------------------
16
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
19
20 #if defined(__BORLANDC__)
21 #pragma hdrstop
22 #endif
23
24 #if wxUSE_THREADS
25
26 #include "wx/thread.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/intl.h"
30 #include "wx/app.h"
31 #include "wx/module.h"
32 #endif
33
34 #include "wx/apptrait.h"
35 #include "wx/scopeguard.h"
36
37 #include "wx/msw/private.h"
38 #include "wx/msw/missing.h"
39 #include "wx/msw/seh.h"
40
41 #include "wx/except.h"
42
43 // must have this symbol defined to get _beginthread/_endthread declarations
44 #ifndef _MT
45 #define _MT
46 #endif
47
48 #if defined(__BORLANDC__)
49 #if !defined(__MT__)
50 // I can't set -tWM in the IDE (anyone?) so have to do this
51 #define __MT__
52 #endif
53
54 #if !defined(__MFC_COMPAT__)
55 // Needed to know about _beginthreadex etc..
56 #define __MFC_COMPAT__
57 #endif
58 #endif // BC++
59
60 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function
61 // which should be used instead of Win32 ::CreateThread() if possible
62 #if defined(__VISUALC__) || \
63 (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \
64 (defined(__GNUG__) && defined(__MSVCRT__)) || \
65 defined(__WATCOMC__) || defined(__MWERKS__)
66
67 #ifndef __WXWINCE__
68 #undef wxUSE_BEGIN_THREAD
69 #define wxUSE_BEGIN_THREAD
70 #endif
71
72 #endif
73
74 #ifdef wxUSE_BEGIN_THREAD
75 // this is where _beginthreadex() is declared
76 #include <process.h>
77
78 // the return type of the thread function entry point: notice that this
79 // type can't hold a pointer under Win64
80 typedef unsigned THREAD_RETVAL;
81
82 // the calling convention of the thread function entry point
83 #define THREAD_CALLCONV __stdcall
84 #else
85 // the settings for CreateThread()
86 typedef DWORD THREAD_RETVAL;
87 #define THREAD_CALLCONV WINAPI
88 #endif
89
90 static const THREAD_RETVAL THREAD_ERROR_EXIT = (THREAD_RETVAL)-1;
91
92 // ----------------------------------------------------------------------------
93 // constants
94 // ----------------------------------------------------------------------------
95
96 // the possible states of the thread ("=>" shows all possible transitions from
97 // this state)
98 enum wxThreadState
99 {
100 STATE_NEW, // didn't start execution yet (=> RUNNING)
101 STATE_RUNNING, // thread is running (=> PAUSED, CANCELED)
102 STATE_PAUSED, // thread is temporarily suspended (=> RUNNING)
103 STATE_CANCELED, // thread should terminate a.s.a.p. (=> EXITED)
104 STATE_EXITED // thread is terminating
105 };
106
107 // ----------------------------------------------------------------------------
108 // this module globals
109 // ----------------------------------------------------------------------------
110
111 // TLS index of the slot where we store the pointer to the current thread
112 static DWORD gs_tlsThisThread = 0xFFFFFFFF;
113
114 // id of the main thread - the one which can call GUI functions without first
115 // calling wxMutexGuiEnter()
116 static DWORD gs_idMainThread = 0;
117
118 // if it's false, some secondary thread is holding the GUI lock
119 static bool gs_bGuiOwnedByMainThread = true;
120
121 // critical section which controls access to all GUI functions: any secondary
122 // thread (i.e. except the main one) must enter this crit section before doing
123 // any GUI calls
124 static wxCriticalSection *gs_critsectGui = NULL;
125
126 // critical section which protects gs_nWaitingForGui variable
127 static wxCriticalSection *gs_critsectWaitingForGui = NULL;
128
129 // critical section which serializes WinThreadStart() and WaitForTerminate()
130 // (this is a potential bottleneck, we use a single crit sect for all threads
131 // in the system, but normally time spent inside it should be quite short)
132 static wxCriticalSection *gs_critsectThreadDelete = NULL;
133
134 // number of threads waiting for GUI in wxMutexGuiEnter()
135 static size_t gs_nWaitingForGui = 0;
136
137 // are we waiting for a thread termination?
138 static bool gs_waitingForThread = false;
139
140 // ============================================================================
141 // Windows implementation of thread and related classes
142 // ============================================================================
143
144 // ----------------------------------------------------------------------------
145 // wxCriticalSection
146 // ----------------------------------------------------------------------------
147
148 wxCriticalSection::wxCriticalSection()
149 {
150 wxCOMPILE_TIME_ASSERT( sizeof(CRITICAL_SECTION) <= sizeof(wxCritSectBuffer),
151 wxCriticalSectionBufferTooSmall );
152
153 ::InitializeCriticalSection((CRITICAL_SECTION *)m_buffer);
154 }
155
156 wxCriticalSection::~wxCriticalSection()
157 {
158 ::DeleteCriticalSection((CRITICAL_SECTION *)m_buffer);
159 }
160
161 void wxCriticalSection::Enter()
162 {
163 ::EnterCriticalSection((CRITICAL_SECTION *)m_buffer);
164 }
165
166 void wxCriticalSection::Leave()
167 {
168 ::LeaveCriticalSection((CRITICAL_SECTION *)m_buffer);
169 }
170
171 // ----------------------------------------------------------------------------
172 // wxMutex
173 // ----------------------------------------------------------------------------
174
175 class wxMutexInternal
176 {
177 public:
178 wxMutexInternal(wxMutexType mutexType);
179 ~wxMutexInternal();
180
181 bool IsOk() const { return m_mutex != NULL; }
182
183 wxMutexError Lock() { return LockTimeout(INFINITE); }
184 wxMutexError Lock(unsigned long ms) { return LockTimeout(ms); }
185 wxMutexError TryLock();
186 wxMutexError Unlock();
187
188 private:
189 wxMutexError LockTimeout(DWORD milliseconds);
190
191 HANDLE m_mutex;
192
193 DECLARE_NO_COPY_CLASS(wxMutexInternal)
194 };
195
196 // all mutexes are recursive under Win32 so we don't use mutexType
197 wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
198 {
199 // create a nameless (hence intra process and always private) mutex
200 m_mutex = ::CreateMutex
201 (
202 NULL, // default secutiry attributes
203 FALSE, // not initially locked
204 NULL // no name
205 );
206
207 if ( !m_mutex )
208 {
209 wxLogLastError(_T("CreateMutex()"));
210 }
211 }
212
213 wxMutexInternal::~wxMutexInternal()
214 {
215 if ( m_mutex )
216 {
217 if ( !::CloseHandle(m_mutex) )
218 {
219 wxLogLastError(_T("CloseHandle(mutex)"));
220 }
221 }
222 }
223
224 wxMutexError wxMutexInternal::TryLock()
225 {
226 const wxMutexError rc = LockTimeout(0);
227
228 // we have a special return code for timeout in this case
229 return rc == wxMUTEX_TIMEOUT ? wxMUTEX_BUSY : rc;
230 }
231
232 wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
233 {
234 DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds);
235 if ( rc == WAIT_ABANDONED )
236 {
237 // the previous caller died without releasing the mutex, but now we can
238 // really lock it
239 wxLogDebug(_T("WaitForSingleObject() returned WAIT_ABANDONED"));
240
241 // use 0 timeout, normally we should always get it
242 rc = ::WaitForSingleObject(m_mutex, 0);
243 }
244
245 switch ( rc )
246 {
247 case WAIT_OBJECT_0:
248 // ok
249 break;
250
251 case WAIT_TIMEOUT:
252 return wxMUTEX_TIMEOUT;
253
254 case WAIT_ABANDONED: // checked for above
255 default:
256 wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock"));
257 // fall through
258
259 case WAIT_FAILED:
260 wxLogLastError(_T("WaitForSingleObject(mutex)"));
261 return wxMUTEX_MISC_ERROR;
262 }
263
264 return wxMUTEX_NO_ERROR;
265 }
266
267 wxMutexError wxMutexInternal::Unlock()
268 {
269 if ( !::ReleaseMutex(m_mutex) )
270 {
271 wxLogLastError(_T("ReleaseMutex()"));
272
273 return wxMUTEX_MISC_ERROR;
274 }
275
276 return wxMUTEX_NO_ERROR;
277 }
278
279 // --------------------------------------------------------------------------
280 // wxSemaphore
281 // --------------------------------------------------------------------------
282
283 // a trivial wrapper around Win32 semaphore
284 class wxSemaphoreInternal
285 {
286 public:
287 wxSemaphoreInternal(int initialcount, int maxcount);
288 ~wxSemaphoreInternal();
289
290 bool IsOk() const { return m_semaphore != NULL; }
291
292 wxSemaError Wait() { return WaitTimeout(INFINITE); }
293
294 wxSemaError TryWait()
295 {
296 wxSemaError rc = WaitTimeout(0);
297 if ( rc == wxSEMA_TIMEOUT )
298 rc = wxSEMA_BUSY;
299
300 return rc;
301 }
302
303 wxSemaError WaitTimeout(unsigned long milliseconds);
304
305 wxSemaError Post();
306
307 private:
308 HANDLE m_semaphore;
309
310 DECLARE_NO_COPY_CLASS(wxSemaphoreInternal)
311 };
312
313 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
314 {
315 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300)
316 if ( maxcount == 0 )
317 {
318 // make it practically infinite
319 maxcount = INT_MAX;
320 }
321
322 m_semaphore = ::CreateSemaphore
323 (
324 NULL, // default security attributes
325 initialcount,
326 maxcount,
327 NULL // no name
328 );
329 #endif
330 if ( !m_semaphore )
331 {
332 wxLogLastError(_T("CreateSemaphore()"));
333 }
334 }
335
336 wxSemaphoreInternal::~wxSemaphoreInternal()
337 {
338 if ( m_semaphore )
339 {
340 if ( !::CloseHandle(m_semaphore) )
341 {
342 wxLogLastError(_T("CloseHandle(semaphore)"));
343 }
344 }
345 }
346
347 wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
348 {
349 DWORD rc = ::WaitForSingleObject( m_semaphore, milliseconds );
350
351 switch ( rc )
352 {
353 case WAIT_OBJECT_0:
354 return wxSEMA_NO_ERROR;
355
356 case WAIT_TIMEOUT:
357 return wxSEMA_TIMEOUT;
358
359 default:
360 wxLogLastError(_T("WaitForSingleObject(semaphore)"));
361 }
362
363 return wxSEMA_MISC_ERROR;
364 }
365
366 wxSemaError wxSemaphoreInternal::Post()
367 {
368 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300)
369 if ( !::ReleaseSemaphore(m_semaphore, 1, NULL /* ptr to previous count */) )
370 {
371 if ( GetLastError() == ERROR_TOO_MANY_POSTS )
372 {
373 return wxSEMA_OVERFLOW;
374 }
375 else
376 {
377 wxLogLastError(_T("ReleaseSemaphore"));
378 return wxSEMA_MISC_ERROR;
379 }
380 }
381
382 return wxSEMA_NO_ERROR;
383 #else
384 return wxSEMA_MISC_ERROR;
385 #endif
386 }
387
388 // ----------------------------------------------------------------------------
389 // wxThread implementation
390 // ----------------------------------------------------------------------------
391
392 // wxThreadInternal class
393 // ----------------------
394
395 class wxThreadInternal
396 {
397 public:
398 wxThreadInternal(wxThread *thread)
399 {
400 m_thread = thread;
401 m_hThread = 0;
402 m_state = STATE_NEW;
403 m_priority = WXTHREAD_DEFAULT_PRIORITY;
404 m_nRef = 1;
405 }
406
407 ~wxThreadInternal()
408 {
409 Free();
410 }
411
412 void Free()
413 {
414 if ( m_hThread )
415 {
416 if ( !::CloseHandle(m_hThread) )
417 {
418 wxLogLastError(wxT("CloseHandle(thread)"));
419 }
420
421 m_hThread = 0;
422 }
423 }
424
425 // create a new (suspended) thread (for the given thread object)
426 bool Create(wxThread *thread, unsigned int stackSize);
427
428 // wait for the thread to terminate, either by itself, or by asking it
429 // (politely, this is not Kill()!) to do it
430 wxThreadError WaitForTerminate(wxCriticalSection& cs,
431 wxThread::ExitCode *pRc,
432 wxThread *threadToDelete = NULL);
433
434 // kill the thread unconditionally
435 wxThreadError Kill();
436
437 // suspend/resume/terminate
438 bool Suspend();
439 bool Resume();
440 void Cancel() { m_state = STATE_CANCELED; }
441
442 // thread state
443 void SetState(wxThreadState state) { m_state = state; }
444 wxThreadState GetState() const { return m_state; }
445
446 // thread priority
447 void SetPriority(unsigned int priority);
448 unsigned int GetPriority() const { return m_priority; }
449
450 // thread handle and id
451 HANDLE GetHandle() const { return m_hThread; }
452 DWORD GetId() const { return m_tid; }
453
454 // the thread function forwarding to DoThreadStart
455 static THREAD_RETVAL THREAD_CALLCONV WinThreadStart(void *thread);
456
457 // really start the thread (if it's not already dead)
458 static THREAD_RETVAL DoThreadStart(wxThread *thread);
459
460 // call OnExit() on the thread
461 static void DoThreadOnExit(wxThread *thread);
462
463
464 void KeepAlive()
465 {
466 if ( m_thread->IsDetached() )
467 ::InterlockedIncrement(&m_nRef);
468 }
469
470 void LetDie()
471 {
472 if ( m_thread->IsDetached() && !::InterlockedDecrement(&m_nRef) )
473 delete m_thread;
474 }
475
476 private:
477 // the thread we're associated with
478 wxThread *m_thread;
479
480 HANDLE m_hThread; // handle of the thread
481 wxThreadState m_state; // state, see wxThreadState enum
482 unsigned int m_priority; // thread priority in "wx" units
483 DWORD m_tid; // thread id
484
485 // number of threads which need this thread to remain alive, when the count
486 // reaches 0 we kill the owning wxThread -- and die ourselves with it
487 LONG m_nRef;
488
489 DECLARE_NO_COPY_CLASS(wxThreadInternal)
490 };
491
492 // small class which keeps a thread alive during its lifetime
493 class wxThreadKeepAlive
494 {
495 public:
496 wxThreadKeepAlive(wxThreadInternal& thrImpl) : m_thrImpl(thrImpl)
497 { m_thrImpl.KeepAlive(); }
498 ~wxThreadKeepAlive()
499 { m_thrImpl.LetDie(); }
500
501 private:
502 wxThreadInternal& m_thrImpl;
503 };
504
505 /* static */
506 void wxThreadInternal::DoThreadOnExit(wxThread *thread)
507 {
508 wxTRY
509 {
510 thread->OnExit();
511 }
512 wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
513 }
514
515 /* static */
516 THREAD_RETVAL wxThreadInternal::DoThreadStart(wxThread *thread)
517 {
518 wxON_BLOCK_EXIT1(DoThreadOnExit, thread);
519
520 THREAD_RETVAL rc = THREAD_ERROR_EXIT;
521
522 wxTRY
523 {
524 // store the thread object in the TLS
525 if ( !::TlsSetValue(gs_tlsThisThread, thread) )
526 {
527 wxLogSysError(_("Can not start thread: error writing TLS."));
528
529 return THREAD_ERROR_EXIT;
530 }
531
532 rc = wxPtrToUInt(thread->Entry());
533 }
534 wxCATCH_ALL( wxTheApp->OnUnhandledException(); )
535
536 return rc;
537 }
538
539 /* static */
540 THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
541 {
542 THREAD_RETVAL rc = THREAD_ERROR_EXIT;
543
544 wxThread * const thread = (wxThread *)param;
545
546 // each thread has its own SEH translator so install our own a.s.a.p.
547 DisableAutomaticSETranslator();
548
549 // first of all, check whether we hadn't been cancelled already and don't
550 // start the user code at all then
551 const bool hasExited = thread->m_internal->GetState() == STATE_EXITED;
552
553 // run the thread function itself inside a SEH try/except block
554 wxSEH_TRY
555 {
556 if ( hasExited )
557 DoThreadOnExit(thread);
558 else
559 rc = DoThreadStart(thread);
560 }
561 wxSEH_HANDLE(THREAD_ERROR_EXIT)
562
563
564 // save IsDetached because thread object can be deleted by joinable
565 // threads after state is changed to STATE_EXITED.
566 const bool isDetached = thread->IsDetached();
567 if ( !hasExited )
568 {
569 // enter m_critsect before changing the thread state
570 //
571 // NB: can't use wxCriticalSectionLocker here as we use SEH and it's
572 // incompatible with C++ object dtors
573 thread->m_critsect.Enter();
574 thread->m_internal->SetState(STATE_EXITED);
575 thread->m_critsect.Leave();
576 }
577
578 // the thread may delete itself now if it wants, we don't need it any more
579 if ( isDetached )
580 thread->m_internal->LetDie();
581
582 return rc;
583 }
584
585 void wxThreadInternal::SetPriority(unsigned int priority)
586 {
587 m_priority = priority;
588
589 // translate wxWidgets priority to the Windows one
590 int win_priority;
591 if (m_priority <= 20)
592 win_priority = THREAD_PRIORITY_LOWEST;
593 else if (m_priority <= 40)
594 win_priority = THREAD_PRIORITY_BELOW_NORMAL;
595 else if (m_priority <= 60)
596 win_priority = THREAD_PRIORITY_NORMAL;
597 else if (m_priority <= 80)
598 win_priority = THREAD_PRIORITY_ABOVE_NORMAL;
599 else if (m_priority <= 100)
600 win_priority = THREAD_PRIORITY_HIGHEST;
601 else
602 {
603 wxFAIL_MSG(wxT("invalid value of thread priority parameter"));
604 win_priority = THREAD_PRIORITY_NORMAL;
605 }
606
607 if ( !::SetThreadPriority(m_hThread, win_priority) )
608 {
609 wxLogSysError(_("Can't set thread priority"));
610 }
611 }
612
613 bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
614 {
615 wxASSERT_MSG( m_state == STATE_NEW && !m_hThread,
616 _T("Create()ing thread twice?") );
617
618 // for compilers which have it, we should use C RTL function for thread
619 // creation instead of Win32 API one because otherwise we will have memory
620 // leaks if the thread uses C RTL (and most threads do)
621 #ifdef wxUSE_BEGIN_THREAD
622
623 // Watcom is reported to not like 0 stack size (which means "use default"
624 // for the other compilers and is also the default value for stackSize)
625 #ifdef __WATCOMC__
626 if ( !stackSize )
627 stackSize = 10240;
628 #endif // __WATCOMC__
629
630 m_hThread = (HANDLE)_beginthreadex
631 (
632 NULL, // default security
633 stackSize,
634 wxThreadInternal::WinThreadStart, // entry point
635 thread,
636 CREATE_SUSPENDED,
637 (unsigned int *)&m_tid
638 );
639 #else // compiler doesn't have _beginthreadex
640 m_hThread = ::CreateThread
641 (
642 NULL, // default security
643 stackSize, // stack size
644 wxThreadInternal::WinThreadStart, // thread entry point
645 (LPVOID)thread, // parameter
646 CREATE_SUSPENDED, // flags
647 &m_tid // [out] thread id
648 );
649 #endif // _beginthreadex/CreateThread
650
651 if ( m_hThread == NULL )
652 {
653 wxLogSysError(_("Can't create thread"));
654
655 return false;
656 }
657
658 if ( m_priority != WXTHREAD_DEFAULT_PRIORITY )
659 {
660 SetPriority(m_priority);
661 }
662
663 return true;
664 }
665
666 wxThreadError wxThreadInternal::Kill()
667 {
668 if ( !::TerminateThread(m_hThread, THREAD_ERROR_EXIT) )
669 {
670 wxLogSysError(_("Couldn't terminate thread"));
671
672 return wxTHREAD_MISC_ERROR;
673 }
674
675 Free();
676
677 return wxTHREAD_NO_ERROR;
678 }
679
680 wxThreadError
681 wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
682 wxThread::ExitCode *pRc,
683 wxThread *threadToDelete)
684 {
685 // prevent the thread C++ object from disappearing as long as we are using
686 // it here
687 wxThreadKeepAlive keepAlive(*this);
688
689
690 // we may either wait passively for the thread to terminate (when called
691 // from Wait()) or ask it to terminate (when called from Delete())
692 bool shouldDelete = threadToDelete != NULL;
693
694 DWORD rc = 0;
695
696 // we might need to resume the thread if it's currently stopped
697 bool shouldResume = false;
698
699 // as Delete() (which calls us) is always safe to call we need to consider
700 // all possible states
701 {
702 wxCriticalSectionLocker lock(cs);
703
704 if ( m_state == STATE_NEW )
705 {
706 if ( shouldDelete )
707 {
708 // WinThreadStart() will see it and terminate immediately, no
709 // need to cancel the thread -- but we still need to resume it
710 // to let it run
711 m_state = STATE_EXITED;
712
713 // we must call Resume() as the thread hasn't been initially
714 // resumed yet (and as Resume() it knows about STATE_EXITED
715 // special case, it won't touch it and WinThreadStart() will
716 // just exit immediately)
717 shouldResume = true;
718 shouldDelete = false;
719 }
720 //else: shouldResume is correctly set to false here, wait until
721 // someone else runs the thread and it finishes
722 }
723 else // running, paused, cancelled or even exited
724 {
725 shouldResume = m_state == STATE_PAUSED;
726 }
727 }
728
729 // resume the thread if it is paused
730 if ( shouldResume )
731 Resume();
732
733 // ask the thread to terminate
734 if ( shouldDelete )
735 {
736 wxCriticalSectionLocker lock(cs);
737
738 Cancel();
739 }
740
741
742 // now wait for thread to finish
743 if ( wxThread::IsMain() )
744 {
745 // set flag for wxIsWaitingForThread()
746 gs_waitingForThread = true;
747 }
748
749 // we can't just wait for the thread to terminate because it might be
750 // calling some GUI functions and so it will never terminate before we
751 // process the Windows messages that result from these functions
752 // (note that even in console applications we might have to process
753 // messages if we use wxExecute() or timers or ...)
754 DWORD result wxDUMMY_INITIALIZE(0);
755 do
756 {
757 if ( wxThread::IsMain() )
758 {
759 // give the thread we're waiting for chance to do the GUI call
760 // it might be in
761 if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
762 {
763 wxMutexGuiLeave();
764 }
765 }
766
767 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
768 if ( traits )
769 {
770 result = traits->WaitForThread(m_hThread);
771 }
772 else // can't wait for the thread
773 {
774 // so kill it below
775 result = 0xFFFFFFFF;
776 }
777
778 switch ( result )
779 {
780 case 0xFFFFFFFF:
781 // error
782 wxLogSysError(_("Can not wait for thread termination"));
783 Kill();
784 return wxTHREAD_KILLED;
785
786 case WAIT_OBJECT_0:
787 // thread we're waiting for terminated
788 break;
789
790 case WAIT_OBJECT_0 + 1:
791 // new message arrived, process it -- but only if we're the
792 // main thread as we don't support processing messages in
793 // the other ones
794 //
795 // NB: we still must include QS_ALLINPUT even when waiting
796 // in a secondary thread because if it had created some
797 // window somehow (possible not even using wxWidgets)
798 // the system might dead lock then
799 if ( wxThread::IsMain() )
800 {
801 if ( traits && !traits->DoMessageFromThreadWait() )
802 {
803 // WM_QUIT received: kill the thread
804 Kill();
805
806 return wxTHREAD_KILLED;
807 }
808 }
809 break;
810
811 default:
812 wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject"));
813 }
814 } while ( result != WAIT_OBJECT_0 );
815
816 if ( wxThread::IsMain() )
817 {
818 gs_waitingForThread = false;
819 }
820
821
822 // although the thread might be already in the EXITED state it might not
823 // have terminated yet and so we are not sure that it has actually
824 // terminated if the "if" above hadn't been taken
825 for ( ;; )
826 {
827 if ( !::GetExitCodeThread(m_hThread, &rc) )
828 {
829 wxLogLastError(wxT("GetExitCodeThread"));
830
831 rc = THREAD_ERROR_EXIT;
832
833 break;
834 }
835
836 if ( rc != STILL_ACTIVE )
837 break;
838
839 // give the other thread some time to terminate, otherwise we may be
840 // starving it
841 ::Sleep(1);
842 }
843
844 if ( pRc )
845 *pRc = wxUIntToPtr(rc);
846
847 // we don't need the thread handle any more in any case
848 Free();
849
850
851 return rc == THREAD_ERROR_EXIT ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
852 }
853
854 bool wxThreadInternal::Suspend()
855 {
856 DWORD nSuspendCount = ::SuspendThread(m_hThread);
857 if ( nSuspendCount == (DWORD)-1 )
858 {
859 wxLogSysError(_("Can not suspend thread %x"), m_hThread);
860
861 return false;
862 }
863
864 m_state = STATE_PAUSED;
865
866 return true;
867 }
868
869 bool wxThreadInternal::Resume()
870 {
871 DWORD nSuspendCount = ::ResumeThread(m_hThread);
872 if ( nSuspendCount == (DWORD)-1 )
873 {
874 wxLogSysError(_("Can not resume thread %x"), m_hThread);
875
876 return false;
877 }
878
879 // don't change the state from STATE_EXITED because it's special and means
880 // we are going to terminate without running any user code - if we did it,
881 // the code in WaitForTerminate() wouldn't work
882 if ( m_state != STATE_EXITED )
883 {
884 m_state = STATE_RUNNING;
885 }
886
887 return true;
888 }
889
890 // static functions
891 // ----------------
892
893 wxThread *wxThread::This()
894 {
895 wxThread *thread = (wxThread *)::TlsGetValue(gs_tlsThisThread);
896
897 // be careful, 0 may be a valid return value as well
898 if ( !thread && (::GetLastError() != NO_ERROR) )
899 {
900 wxLogSysError(_("Couldn't get the current thread pointer"));
901
902 // return NULL...
903 }
904
905 return thread;
906 }
907
908 bool wxThread::IsMain()
909 {
910 return ::GetCurrentThreadId() == gs_idMainThread || gs_idMainThread == 0;
911 }
912
913 void wxThread::Yield()
914 {
915 // 0 argument to Sleep() is special and means to just give away the rest of
916 // our timeslice
917 ::Sleep(0);
918 }
919
920 int wxThread::GetCPUCount()
921 {
922 SYSTEM_INFO si;
923 GetSystemInfo(&si);
924
925 return si.dwNumberOfProcessors;
926 }
927
928 unsigned long wxThread::GetCurrentId()
929 {
930 return (unsigned long)::GetCurrentThreadId();
931 }
932
933 bool wxThread::SetConcurrency(size_t WXUNUSED_IN_WINCE(level))
934 {
935 #ifdef __WXWINCE__
936 return false;
937 #else
938 wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") );
939
940 // ok only for the default one
941 if ( level == 0 )
942 return 0;
943
944 // get system affinity mask first
945 HANDLE hProcess = ::GetCurrentProcess();
946 DWORD_PTR dwProcMask, dwSysMask;
947 if ( ::GetProcessAffinityMask(hProcess, &dwProcMask, &dwSysMask) == 0 )
948 {
949 wxLogLastError(_T("GetProcessAffinityMask"));
950
951 return false;
952 }
953
954 // how many CPUs have we got?
955 if ( dwSysMask == 1 )
956 {
957 // don't bother with all this complicated stuff - on a single
958 // processor system it doesn't make much sense anyhow
959 return level == 1;
960 }
961
962 // calculate the process mask: it's a bit vector with one bit per
963 // processor; we want to schedule the process to run on first level
964 // CPUs
965 DWORD bit = 1;
966 while ( bit )
967 {
968 if ( dwSysMask & bit )
969 {
970 // ok, we can set this bit
971 dwProcMask |= bit;
972
973 // another process added
974 if ( --level == 0 )
975 {
976 // and that's enough
977 break;
978 }
979 }
980
981 // next bit
982 bit <<= 1;
983 }
984
985 // could we set all bits?
986 if ( level != 0 )
987 {
988 wxLogDebug(_T("bad level %u in wxThread::SetConcurrency()"), level);
989
990 return false;
991 }
992
993 // set it: we can't link to SetProcessAffinityMask() because it doesn't
994 // exist in Win9x, use RT binding instead
995
996 typedef BOOL (WINAPI *SETPROCESSAFFINITYMASK)(HANDLE, DWORD_PTR);
997
998 // can use static var because we're always in the main thread here
999 static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask = NULL;
1000
1001 if ( !pfnSetProcessAffinityMask )
1002 {
1003 HMODULE hModKernel = ::LoadLibrary(_T("kernel32"));
1004 if ( hModKernel )
1005 {
1006 pfnSetProcessAffinityMask = (SETPROCESSAFFINITYMASK)
1007 ::GetProcAddress(hModKernel, "SetProcessAffinityMask");
1008 }
1009
1010 // we've discovered a MT version of Win9x!
1011 wxASSERT_MSG( pfnSetProcessAffinityMask,
1012 _T("this system has several CPUs but no SetProcessAffinityMask function?") );
1013 }
1014
1015 if ( !pfnSetProcessAffinityMask )
1016 {
1017 // msg given above - do it only once
1018 return false;
1019 }
1020
1021 if ( pfnSetProcessAffinityMask(hProcess, dwProcMask) == 0 )
1022 {
1023 wxLogLastError(_T("SetProcessAffinityMask"));
1024
1025 return false;
1026 }
1027
1028 return true;
1029 #endif // __WXWINCE__/!__WXWINCE__
1030 }
1031
1032 // ctor and dtor
1033 // -------------
1034
1035 wxThread::wxThread(wxThreadKind kind)
1036 {
1037 m_internal = new wxThreadInternal(this);
1038
1039 m_isDetached = kind == wxTHREAD_DETACHED;
1040 }
1041
1042 wxThread::~wxThread()
1043 {
1044 delete m_internal;
1045 }
1046
1047 // create/start thread
1048 // -------------------
1049
1050 wxThreadError wxThread::Create(unsigned int stackSize)
1051 {
1052 wxCriticalSectionLocker lock(m_critsect);
1053
1054 if ( !m_internal->Create(this, stackSize) )
1055 return wxTHREAD_NO_RESOURCE;
1056
1057 return wxTHREAD_NO_ERROR;
1058 }
1059
1060 wxThreadError wxThread::Run()
1061 {
1062 wxCriticalSectionLocker lock(m_critsect);
1063
1064 if ( m_internal->GetState() != STATE_NEW )
1065 {
1066 // actually, it may be almost any state at all, not only STATE_RUNNING
1067 return wxTHREAD_RUNNING;
1068 }
1069
1070 // the thread has just been created and is still suspended - let it run
1071 return Resume();
1072 }
1073
1074 // suspend/resume thread
1075 // ---------------------
1076
1077 wxThreadError wxThread::Pause()
1078 {
1079 wxCriticalSectionLocker lock(m_critsect);
1080
1081 return m_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
1082 }
1083
1084 wxThreadError wxThread::Resume()
1085 {
1086 wxCriticalSectionLocker lock(m_critsect);
1087
1088 return m_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
1089 }
1090
1091 // stopping thread
1092 // ---------------
1093
1094 wxThread::ExitCode wxThread::Wait()
1095 {
1096 ExitCode rc = wxUIntToPtr(THREAD_ERROR_EXIT);
1097
1098 // although under Windows we can wait for any thread, it's an error to
1099 // wait for a detached one in wxWin API
1100 wxCHECK_MSG( !IsDetached(), rc,
1101 _T("wxThread::Wait(): can't wait for detached thread") );
1102
1103 (void)m_internal->WaitForTerminate(m_critsect, &rc);
1104
1105 return rc;
1106 }
1107
1108 wxThreadError wxThread::Delete(ExitCode *pRc)
1109 {
1110 return m_internal->WaitForTerminate(m_critsect, pRc, this);
1111 }
1112
1113 wxThreadError wxThread::Kill()
1114 {
1115 if ( !IsRunning() )
1116 return wxTHREAD_NOT_RUNNING;
1117
1118 wxThreadError rc = m_internal->Kill();
1119
1120 if ( IsDetached() )
1121 {
1122 delete this;
1123 }
1124 else // joinable
1125 {
1126 // update the status of the joinable thread
1127 wxCriticalSectionLocker lock(m_critsect);
1128 m_internal->SetState(STATE_EXITED);
1129 }
1130
1131 return rc;
1132 }
1133
1134 void wxThread::Exit(ExitCode status)
1135 {
1136 m_internal->Free();
1137
1138 if ( IsDetached() )
1139 {
1140 delete this;
1141 }
1142 else // joinable
1143 {
1144 // update the status of the joinable thread
1145 wxCriticalSectionLocker lock(m_critsect);
1146 m_internal->SetState(STATE_EXITED);
1147 }
1148
1149 #ifdef wxUSE_BEGIN_THREAD
1150 _endthreadex(wxPtrToUInt(status));
1151 #else // !VC++
1152 ::ExitThread((DWORD)status);
1153 #endif // VC++/!VC++
1154
1155 wxFAIL_MSG(wxT("Couldn't return from ExitThread()!"));
1156 }
1157
1158 // priority setting
1159 // ----------------
1160
1161 void wxThread::SetPriority(unsigned int prio)
1162 {
1163 wxCriticalSectionLocker lock(m_critsect);
1164
1165 m_internal->SetPriority(prio);
1166 }
1167
1168 unsigned int wxThread::GetPriority() const
1169 {
1170 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1171
1172 return m_internal->GetPriority();
1173 }
1174
1175 unsigned long wxThread::GetId() const
1176 {
1177 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1178
1179 return (unsigned long)m_internal->GetId();
1180 }
1181
1182 bool wxThread::IsRunning() const
1183 {
1184 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1185
1186 return m_internal->GetState() == STATE_RUNNING;
1187 }
1188
1189 bool wxThread::IsAlive() const
1190 {
1191 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1192
1193 return (m_internal->GetState() == STATE_RUNNING) ||
1194 (m_internal->GetState() == STATE_PAUSED);
1195 }
1196
1197 bool wxThread::IsPaused() const
1198 {
1199 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1200
1201 return m_internal->GetState() == STATE_PAUSED;
1202 }
1203
1204 bool wxThread::TestDestroy()
1205 {
1206 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
1207
1208 return m_internal->GetState() == STATE_CANCELED;
1209 }
1210
1211 // ----------------------------------------------------------------------------
1212 // Automatic initialization for thread module
1213 // ----------------------------------------------------------------------------
1214
1215 class wxThreadModule : public wxModule
1216 {
1217 public:
1218 virtual bool OnInit();
1219 virtual void OnExit();
1220
1221 private:
1222 DECLARE_DYNAMIC_CLASS(wxThreadModule)
1223 };
1224
1225 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
1226
1227 bool wxThreadModule::OnInit()
1228 {
1229 // allocate TLS index for storing the pointer to the current thread
1230 gs_tlsThisThread = ::TlsAlloc();
1231 if ( gs_tlsThisThread == 0xFFFFFFFF )
1232 {
1233 // in normal circumstances it will only happen if all other
1234 // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other
1235 // words, this should never happen
1236 wxLogSysError(_("Thread module initialization failed: impossible to allocate index in thread local storage"));
1237
1238 return false;
1239 }
1240
1241 // main thread doesn't have associated wxThread object, so store 0 in the
1242 // TLS instead
1243 if ( !::TlsSetValue(gs_tlsThisThread, (LPVOID)0) )
1244 {
1245 ::TlsFree(gs_tlsThisThread);
1246 gs_tlsThisThread = 0xFFFFFFFF;
1247
1248 wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage"));
1249
1250 return false;
1251 }
1252
1253 gs_critsectWaitingForGui = new wxCriticalSection();
1254
1255 gs_critsectGui = new wxCriticalSection();
1256 gs_critsectGui->Enter();
1257
1258 gs_critsectThreadDelete = new wxCriticalSection;
1259
1260 // no error return for GetCurrentThreadId()
1261 gs_idMainThread = ::GetCurrentThreadId();
1262
1263 return true;
1264 }
1265
1266 void wxThreadModule::OnExit()
1267 {
1268 if ( !::TlsFree(gs_tlsThisThread) )
1269 {
1270 wxLogLastError(wxT("TlsFree failed."));
1271 }
1272
1273 delete gs_critsectThreadDelete;
1274 gs_critsectThreadDelete = NULL;
1275
1276 if ( gs_critsectGui )
1277 {
1278 gs_critsectGui->Leave();
1279 delete gs_critsectGui;
1280 gs_critsectGui = NULL;
1281 }
1282
1283 delete gs_critsectWaitingForGui;
1284 gs_critsectWaitingForGui = NULL;
1285 }
1286
1287 // ----------------------------------------------------------------------------
1288 // under Windows, these functions are implemented using a critical section and
1289 // not a mutex, so the names are a bit confusing
1290 // ----------------------------------------------------------------------------
1291
1292 void wxMutexGuiEnterImpl()
1293 {
1294 // this would dead lock everything...
1295 wxASSERT_MSG( !wxThread::IsMain(),
1296 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
1297
1298 // the order in which we enter the critical sections here is crucial!!
1299
1300 // set the flag telling to the main thread that we want to do some GUI
1301 {
1302 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1303
1304 gs_nWaitingForGui++;
1305 }
1306
1307 wxWakeUpMainThread();
1308
1309 // now we may block here because the main thread will soon let us in
1310 // (during the next iteration of OnIdle())
1311 gs_critsectGui->Enter();
1312 }
1313
1314 void wxMutexGuiLeaveImpl()
1315 {
1316 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1317
1318 if ( wxThread::IsMain() )
1319 {
1320 gs_bGuiOwnedByMainThread = false;
1321 }
1322 else
1323 {
1324 // decrement the number of threads waiting for GUI access now
1325 wxASSERT_MSG( gs_nWaitingForGui > 0,
1326 wxT("calling wxMutexGuiLeave() without entering it first?") );
1327
1328 gs_nWaitingForGui--;
1329
1330 wxWakeUpMainThread();
1331 }
1332
1333 gs_critsectGui->Leave();
1334 }
1335
1336 void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
1337 {
1338 wxASSERT_MSG( wxThread::IsMain(),
1339 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
1340
1341 wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
1342
1343 if ( gs_nWaitingForGui == 0 )
1344 {
1345 // no threads are waiting for GUI - so we may acquire the lock without
1346 // any danger (but only if we don't already have it)
1347 if ( !wxGuiOwnedByMainThread() )
1348 {
1349 gs_critsectGui->Enter();
1350
1351 gs_bGuiOwnedByMainThread = true;
1352 }
1353 //else: already have it, nothing to do
1354 }
1355 else
1356 {
1357 // some threads are waiting, release the GUI lock if we have it
1358 if ( wxGuiOwnedByMainThread() )
1359 {
1360 wxMutexGuiLeave();
1361 }
1362 //else: some other worker thread is doing GUI
1363 }
1364 }
1365
1366 bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread()
1367 {
1368 return gs_bGuiOwnedByMainThread;
1369 }
1370
1371 // wake up the main thread if it's in ::GetMessage()
1372 void WXDLLIMPEXP_BASE wxWakeUpMainThread()
1373 {
1374 // sending any message would do - hopefully WM_NULL is harmless enough
1375 if ( !::PostThreadMessage(gs_idMainThread, WM_NULL, 0, 0) )
1376 {
1377 // should never happen
1378 wxLogLastError(wxT("PostThreadMessage(WM_NULL)"));
1379 }
1380 }
1381
1382 bool WXDLLIMPEXP_BASE wxIsWaitingForThread()
1383 {
1384 return gs_waitingForThread;
1385 }
1386
1387 // ----------------------------------------------------------------------------
1388 // include common implementation code
1389 // ----------------------------------------------------------------------------
1390
1391 #include "wx/thrimpl.cpp"
1392
1393 #endif // wxUSE_THREADS