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