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