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