/[pcsx2_0.9.7]/branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/thread.cpp
ViewVC logotype

Contents of /branch/r3113_0.9.7_beta/3rdparty/wxWidgets/src/msw/thread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22