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