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