]> git.saurik.com Git - wxWidgets.git/blame - src/os2/thread.cpp
Compile fix for wxDataFormat cast,
[wxWidgets.git] / src / os2 / thread.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: thread.cpp
3// Purpose: wxThread Implementation. For Unix ports, see e.g. src/gtk
4// Author: Original from Wolfram Gloger/Guilhem Lavaux
d90895ac 5// Modified by: David Webster
0e320a79
DW
6// Created: 04/22/98
7// RCS-ID: $Id$
8// Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
d90895ac
DW
12// ----------------------------------------------------------------------------
13// headers
14// ----------------------------------------------------------------------------
0e320a79 15
d90895ac
DW
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
0e320a79
DW
18
19#if wxUSE_THREADS
20
d90895ac
DW
21#include <stdio.h>
22
23#define INCL_DOS
24#include <os2.h>
25
26#include "wx/module.h"
27#include "wx/thread.h"
28
29// the possible states of the thread ("=>" shows all possible transitions from
30// this state)
31enum wxThreadState
32{
33 STATE_NEW, // didn't start execution yet (=> RUNNING)
34 STATE_RUNNING, // thread is running (=> PAUSED, CANCELED)
35 STATE_PAUSED, // thread is temporarily suspended (=> RUNNING)
36 STATE_CANCELED, // thread should terminate a.s.a.p. (=> EXITED)
37 STATE_EXITED // thread is terminating
0e320a79
DW
38};
39
d90895ac
DW
40// ----------------------------------------------------------------------------
41// static variables
42// ----------------------------------------------------------------------------
0e320a79 43
d90895ac
DW
44// TLS index of the slot where we store the pointer to the current thread
45static DWORD s_tlsThisThread = 0xFFFFFFFF;
0e320a79 46
d90895ac
DW
47// id of the main thread - the one which can call GUI functions without first
48// calling wxMutexGuiEnter()
49static DWORD s_idMainThread = 0;
50
51// if it's FALSE, some secondary thread is holding the GUI lock
52static bool s_bGuiOwnedByMainThread = TRUE;
0e320a79 53
d90895ac
DW
54// critical section which controls access to all GUI functions: any secondary
55// thread (i.e. except the main one) must enter this crit section before doing
56// any GUI calls
57static wxCriticalSection *s_critsectGui = NULL;
58
59// critical section which protects s_nWaitingForGui variable
60static wxCriticalSection *s_critsectWaitingForGui = NULL;
61
62// number of threads waiting for GUI in wxMutexGuiEnter()
63static size_t s_nWaitingForGui = 0;
64
65// are we waiting for a thread termination?
66static bool s_waitingForThread = FALSE;
67
68// ============================================================================
69// Windows implementation of thread classes
70// ============================================================================
71
72// ----------------------------------------------------------------------------
73// wxMutex implementation
74// ----------------------------------------------------------------------------
75class wxMutexInternal
76{
0e320a79 77public:
d90895ac 78 HANDLE p_mutex;
0e320a79
DW
79};
80
81wxMutex::wxMutex()
82{
83 p_internal = new wxMutexInternal;
d90895ac
DW
84// p_internal->p_mutex = CreateMutex(NULL, FALSE, NULL);
85 if ( !p_internal->p_mutex )
86 {
87 wxLogSysError(_("Can not create mutex."));
88 }
89
0e320a79
DW
90 m_locked = 0;
91}
92
93wxMutex::~wxMutex()
94{
95 if (m_locked > 0)
d90895ac
DW
96 wxLogDebug(wxT("Warning: freeing a locked mutex (%d locks)."), m_locked);
97// CloseHandle(p_internal->p_mutex);
0e320a79
DW
98}
99
100wxMutexError wxMutex::Lock()
101{
d90895ac
DW
102 DWORD ret;
103
104// TODO:
105/*
106 ret = WaitForSingleObject(p_internal->p_mutex, INFINITE);
107 switch ( ret )
108 {
109 case WAIT_ABANDONED:
110 return wxMUTEX_BUSY;
111
112 case WAIT_OBJECT_0:
113 // ok
114 break;
115
116 case WAIT_FAILED:
117 wxLogSysError(_("Couldn't acquire a mutex lock"));
118 return wxMUTEX_MISC_ERROR;
119
120 case WAIT_TIMEOUT:
121 default:
122 wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock"));
123 }
124
0e320a79 125 m_locked++;
d90895ac 126*/
0e320a79
DW
127 return wxMUTEX_NO_ERROR;
128}
129
130wxMutexError wxMutex::TryLock()
131{
d90895ac
DW
132 DWORD ret;
133
134// TODO:
135/*
136 ret = WaitForSingleObject(p_internal->p_mutex, 0);
137 if (ret == WAIT_TIMEOUT || ret == WAIT_ABANDONED)
138 return wxMUTEX_BUSY;
139
0e320a79 140 m_locked++;
d90895ac 141*/
0e320a79
DW
142 return wxMUTEX_NO_ERROR;
143}
144
145wxMutexError wxMutex::Unlock()
146{
147 if (m_locked > 0)
148 m_locked--;
149
d90895ac
DW
150 BOOL ret = 0; // TODO: ReleaseMutex(p_internal->p_mutex);
151 if ( ret == 0 )
152 {
153 wxLogSysError(_("Couldn't release a mutex"));
154 return wxMUTEX_MISC_ERROR;
155 }
156
0e320a79
DW
157 return wxMUTEX_NO_ERROR;
158}
159
d90895ac
DW
160// ----------------------------------------------------------------------------
161// wxCondition implementation
162// ----------------------------------------------------------------------------
163
164class wxConditionInternal
165{
0e320a79 166public:
d90895ac
DW
167 HANDLE event;
168 int waiters;
0e320a79
DW
169};
170
171wxCondition::wxCondition()
172{
173 p_internal = new wxConditionInternal;
d90895ac
DW
174// TODO:
175/*
176 p_internal->event = CreateEvent(NULL, FALSE, FALSE, NULL);
177 if ( !p_internal->event )
178 {
179 wxLogSysError(_("Can not create event object."));
180 }
181*/
0e320a79
DW
182 p_internal->waiters = 0;
183}
184
185wxCondition::~wxCondition()
186{
d90895ac 187// CloseHandle(p_internal->event);
0e320a79
DW
188}
189
190void wxCondition::Wait(wxMutex& mutex)
191{
192 mutex.Unlock();
193 p_internal->waiters++;
d90895ac 194// WaitForSingleObject(p_internal->event, INFINITE);
0e320a79
DW
195 p_internal->waiters--;
196 mutex.Lock();
197}
198
d90895ac
DW
199bool wxCondition::Wait(wxMutex& mutex,
200 unsigned long sec,
0e320a79
DW
201 unsigned long nsec)
202{
d90895ac
DW
203 DWORD ret;
204
0e320a79
DW
205 mutex.Unlock();
206 p_internal->waiters++;
d90895ac 207// ret = WaitForSingleObject(p_internal->event, (sec*1000)+(nsec/1000000));
0e320a79
DW
208 p_internal->waiters--;
209 mutex.Lock();
210
d90895ac 211// return (ret != WAIT_TIMEOUT);
0e320a79
DW
212 return FALSE;
213}
214
215void wxCondition::Signal()
216{
d90895ac 217// SetEvent(p_internal->event);
0e320a79
DW
218}
219
220void wxCondition::Broadcast()
221{
d90895ac
DW
222 int i;
223
224// TODO:
225/*
226 for (i=0;i<p_internal->waiters;i++)
227 {
228 if ( SetEvent(p_internal->event) == 0 )
229 {
230 wxLogSysError(_("Couldn't change the state of event object."));
231 }
232 }
233*/
0e320a79
DW
234}
235
d90895ac
DW
236// ----------------------------------------------------------------------------
237// wxCriticalSection implementation
238// ----------------------------------------------------------------------------
239#define CRITICAL_SECTION ULONG
240class wxCriticalSectionInternal
241{
0e320a79 242public:
d90895ac
DW
243 // init the critical section object
244 wxCriticalSectionInternal()
245 { //::InitializeCriticalSection(&m_data);
246 }
247
248 // implicit cast to the associated data
249 operator CRITICAL_SECTION *() { return &m_data; }
250
251 // free the associated ressources
252 ~wxCriticalSectionInternal()
253 { //::DeleteCriticalSection(&m_data);
254 }
255
256private:
257 CRITICAL_SECTION m_data;
0e320a79
DW
258};
259
d90895ac
DW
260wxCriticalSection::wxCriticalSection()
261{
262 m_critsect = new wxCriticalSectionInternal;
263}
264
265wxCriticalSection::~wxCriticalSection()
266{
267 delete m_critsect;
268}
269
270void wxCriticalSection::Enter()
271{
272//TODO: ::EnterCriticalSection(*m_critsect);
273}
274
275void wxCriticalSection::Leave()
276{
277// TODO: ::LeaveCriticalSection(*m_critsect);
278}
279
280// ----------------------------------------------------------------------------
281// wxThread implementation
282// ----------------------------------------------------------------------------
283
284// wxThreadInternal class
285// ----------------------
286
287class wxThreadInternal
288{
289public:
290 wxThreadInternal()
291 {
292 m_hThread = 0;
293 m_state = STATE_NEW;
294 m_priority = 0; // TODO: WXTHREAD_DEFAULT_PRIORITY;
295 }
296
297 // create a new (suspended) thread (for the given thread object)
298 bool Create(wxThread *thread);
299
300 // suspend/resume/terminate
301 bool Suspend();
302 bool Resume();
303 void Cancel() { m_state = STATE_CANCELED; }
304
305 // thread state
306 void SetState(wxThreadState state) { m_state = state; }
307 wxThreadState GetState() const { return m_state; }
308
309 // thread priority
310 void SetPriority(unsigned int priority) { m_priority = priority; }
311 unsigned int GetPriority() const { return m_priority; }
312
313 // thread handle and id
314 HANDLE GetHandle() const { return m_hThread; }
315 DWORD GetId() const { return m_tid; }
316
317 // thread function
318 static DWORD OS2ThreadStart(wxThread *thread);
319
320private:
321 HANDLE m_hThread; // handle of the thread
322 wxThreadState m_state; // state, see wxThreadState enum
323 unsigned int m_priority; // thread priority in "wx" units
324 DWORD m_tid; // thread id
325};
326
327DWORD wxThreadInternal::OS2ThreadStart(wxThread *thread)
328{
329 // store the thread object in the TLS
330// TODO:
331/*
332 if ( !::TlsSetValue(s_tlsThisThread, thread) )
333 {
334 wxLogSysError(_("Can not start thread: error writing TLS."));
335
336 return (DWORD)-1;
337 }
338*/
339 DWORD ret = (DWORD)thread->Entry();
340 thread->p_internal->SetState(STATE_EXITED);
341 thread->OnExit();
342
343 delete thread;
344
345 return ret;
346}
347
348bool wxThreadInternal::Create(wxThread *thread)
349{
350// TODO:
351/*
352 m_hThread = ::CreateThread
353 (
354 NULL, // default security
355 0, // default stack size
356 (LPTHREAD_START_ROUTINE) // thread entry point
357 wxThreadInternal::OS2ThreadStart, //
358 (LPVOID)thread, // parameter
359 CREATE_SUSPENDED, // flags
360 &m_tid // [out] thread id
361 );
362
363 if ( m_hThread == NULL )
364 {
365 wxLogSysError(_("Can't create thread"));
366
367 return FALSE;
368 }
369
370 // translate wxWindows priority to the Windows one
371 int win_priority;
372 if (m_priority <= 20)
373 win_priority = THREAD_PRIORITY_LOWEST;
374 else if (m_priority <= 40)
375 win_priority = THREAD_PRIORITY_BELOW_NORMAL;
376 else if (m_priority <= 60)
377 win_priority = THREAD_PRIORITY_NORMAL;
378 else if (m_priority <= 80)
379 win_priority = THREAD_PRIORITY_ABOVE_NORMAL;
380 else if (m_priority <= 100)
381 win_priority = THREAD_PRIORITY_HIGHEST;
382 else
383 {
384 wxFAIL_MSG(wxT("invalid value of thread priority parameter"));
385 win_priority = THREAD_PRIORITY_NORMAL;
386 }
387
388 if ( ::SetThreadPriority(m_hThread, win_priority) == 0 )
389 {
390 wxLogSysError(_("Can't set thread priority"));
391 }
392*/
393 return FALSE;
394}
395
396bool wxThreadInternal::Suspend()
397{
398// TODO:
399/*
400 DWORD nSuspendCount = ::SuspendThread(m_hThread);
401 if ( nSuspendCount == (DWORD)-1 )
402 {
403 wxLogSysError(_("Can not suspend thread %x"), m_hThread);
404
405 return FALSE;
406 }
407
408 m_state = STATE_PAUSED;
409*/
410 return FALSE;
411}
412
413bool wxThreadInternal::Resume()
414{
415// TODO:
416/*
417 DWORD nSuspendCount = ::ResumeThread(m_hThread);
418 if ( nSuspendCount == (DWORD)-1 )
419 {
420 wxLogSysError(_("Can not resume thread %x"), m_hThread);
421
422 return FALSE;
423 }
424
425 m_state = STATE_RUNNING;
426*/
427 return FALSE;
428}
429
430// static functions
431// ----------------
432
433wxThread *wxThread::This()
434{
435 wxThread *thread = NULL; // TODO (wxThread *)::TlsGetValue(s_tlsThisThread);
436
437// TODO:
438/*
439 // be careful, 0 may be a valid return value as well
440 if ( !thread && (::GetLastError() != NO_ERROR) )
441 {
442 wxLogSysError(_("Couldn't get the current thread pointer"));
443
444 // return NULL...
445 }
446*/
447 return thread;
448}
449
450bool wxThread::IsMain()
451{
452// TODO: return ::GetCurrentThreadId() == s_idMainThread;
453 return FALSE;
454}
455
456#ifdef Yield
457 #undef Yield
458#endif
459
460void wxThread::Yield()
461{
462 // 0 argument to Sleep() is special
463 ::DosSleep(0);
464}
465
466void wxThread::Sleep(unsigned long milliseconds)
467{
468 ::DosSleep(milliseconds);
469}
470
471// create/start thread
472// -------------------
473
0e320a79
DW
474wxThreadError wxThread::Create()
475{
d90895ac
DW
476 if ( !p_internal->Create(this) )
477 return wxTHREAD_NO_RESOURCE;
478
0e320a79
DW
479 return wxTHREAD_NO_ERROR;
480}
481
d90895ac 482wxThreadError wxThread::Run()
0e320a79 483{
d90895ac
DW
484 wxCriticalSectionLocker lock(m_critsect);
485
486 if ( p_internal->GetState() != STATE_NEW )
487 {
488 // actually, it may be almost any state at all, not only STATE_RUNNING
489 return wxTHREAD_RUNNING;
490 }
491
492 return Resume();
0e320a79
DW
493}
494
d90895ac
DW
495// suspend/resume thread
496// ---------------------
497
0e320a79
DW
498wxThreadError wxThread::Pause()
499{
d90895ac
DW
500 wxCriticalSectionLocker lock(m_critsect);
501
502 return p_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
0e320a79
DW
503}
504
505wxThreadError wxThread::Resume()
506{
d90895ac 507 wxCriticalSectionLocker lock(m_critsect);
0e320a79 508
d90895ac 509 return p_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
0e320a79
DW
510}
511
d90895ac
DW
512// stopping thread
513// ---------------
514
515wxThread::ExitCode wxThread::Delete()
0e320a79 516{
d90895ac
DW
517 ExitCode rc = 0;
518
519 // Delete() is always safe to call, so consider all possible states
520 if ( IsPaused() )
521 Resume();
522
523 if ( IsRunning() )
524 {
525 if ( IsMain() )
526 {
527 // set flag for wxIsWaitingForThread()
528 s_waitingForThread = TRUE;
529
530 wxBeginBusyCursor();
531 }
532
533 HANDLE hThread;
534 {
535 wxCriticalSectionLocker lock(m_critsect);
536
537 p_internal->Cancel();
538 hThread = p_internal->GetHandle();
539 }
540
541 // we can't just wait for the thread to terminate because it might be
542 // calling some GUI functions and so it will never terminate before we
543 // process the Windows messages that result from these functions
544 DWORD result;
545// TODO:
546/*
547 do
548 {
549 result = ::MsgWaitForMultipleObjects
550 (
551 1, // number of objects to wait for
552 &hThread, // the objects
553 FALSE, // don't wait for all objects
554 INFINITE, // no timeout
555 QS_ALLEVENTS // return as soon as there are any events
556 );
557
558 switch ( result )
559 {
560 case 0xFFFFFFFF:
561 // error
562 wxLogSysError(_("Can not wait for thread termination"));
563 Kill();
564 return (ExitCode)-1;
565
566 case WAIT_OBJECT_0:
567 // thread we're waiting for terminated
568 break;
569
570 case WAIT_OBJECT_0 + 1:
571 // new message arrived, process it
572 if ( !wxTheApp->DoMessage() )
573 {
574 // WM_QUIT received: kill the thread
575 Kill();
576
577 return (ExitCode)-1;
578 }
579
580 if ( IsMain() )
581 {
582 // give the thread we're waiting for chance to exit
583 // from the GUI call it might have been in
584 if ( (s_nWaitingForGui > 0) && wxGuiOwnedByMainThread() )
585 {
586 wxMutexGuiLeave();
587 }
588 }
589
590 break;
591
592 default:
593 wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject"));
594 }
595 } while ( result != WAIT_OBJECT_0 );
596*/
597 if ( IsMain() )
598 {
599 s_waitingForThread = FALSE;
600
601 wxEndBusyCursor();
602 }
603
604// TODO:
605/*
606 if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) )
607 {
608 wxLogLastError("GetExitCodeThread");
609
610 rc = (ExitCode)-1;
611 }
612
613 wxASSERT_MSG( (LPVOID)rc != (LPVOID)STILL_ACTIVE,
614 wxT("thread must be already terminated.") );
615
616 ::CloseHandle(hThread);
617*/
618 }
619
620 return rc;
0e320a79
DW
621}
622
d90895ac 623wxThreadError wxThread::Kill()
0e320a79 624{
d90895ac
DW
625 if ( !IsRunning() )
626 return wxTHREAD_NOT_RUNNING;
627
628// TODO:
629/*
630 if ( !::TerminateThread(p_internal->GetHandle(), (DWORD)-1) )
631 {
632 wxLogSysError(_("Couldn't terminate thread"));
633
634 return wxTHREAD_MISC_ERROR;
635 }
636*/
637 delete this;
638
639 return wxTHREAD_NO_ERROR;
0e320a79
DW
640}
641
d90895ac 642void wxThread::Exit(void *status)
0e320a79 643{
d90895ac
DW
644 delete this;
645
646// TODO: ::ExitThread((DWORD)status);
647
648 wxFAIL_MSG(wxT("Couldn't return from ExitThread()!"));
0e320a79
DW
649}
650
d90895ac 651void wxThread::SetPriority(unsigned int prio)
0e320a79 652{
d90895ac
DW
653 wxCriticalSectionLocker lock(m_critsect);
654
655 p_internal->SetPriority(prio);
0e320a79
DW
656}
657
d90895ac 658unsigned int wxThread::GetPriority() const
0e320a79 659{
d90895ac
DW
660 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
661
662 return p_internal->GetPriority();
0e320a79
DW
663}
664
665unsigned long wxThread::GetID() const
666{
d90895ac
DW
667 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
668
669 return (unsigned long)p_internal->GetId();
0e320a79
DW
670}
671
d90895ac 672bool wxThread::IsRunning() const
0e320a79 673{
d90895ac
DW
674 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
675
676 return p_internal->GetState() == STATE_RUNNING;
0e320a79 677}
0e320a79
DW
678
679bool wxThread::IsAlive() const
680{
d90895ac
DW
681 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
682
683 return (p_internal->GetState() == STATE_RUNNING) ||
684 (p_internal->GetState() == STATE_PAUSED);
0e320a79
DW
685}
686
d90895ac 687bool wxThread::IsPaused() const
0e320a79 688{
d90895ac
DW
689 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
690
691 return (p_internal->GetState() == STATE_PAUSED);
0e320a79
DW
692}
693
d90895ac 694bool wxThread::TestDestroy()
0e320a79 695{
d90895ac
DW
696 wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
697
698 return p_internal->GetState() == STATE_CANCELED;
0e320a79
DW
699}
700
701wxThread::wxThread()
702{
703 p_internal = new wxThreadInternal();
0e320a79
DW
704}
705
706wxThread::~wxThread()
707{
0e320a79
DW
708 delete p_internal;
709}
710
d90895ac
DW
711// ----------------------------------------------------------------------------
712// Automatic initialization for thread module
713// ----------------------------------------------------------------------------
0e320a79 714
d90895ac
DW
715class wxThreadModule : public wxModule
716{
0e320a79 717public:
d90895ac
DW
718 virtual bool OnInit();
719 virtual void OnExit();
0e320a79 720
d90895ac
DW
721private:
722 DECLARE_DYNAMIC_CLASS(wxThreadModule)
0e320a79
DW
723};
724
725IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
726
d90895ac
DW
727bool wxThreadModule::OnInit()
728{
729 // allocate TLS index for storing the pointer to the current thread
730// TODO:
731/*
732 s_tlsThisThread = ::TlsAlloc();
733 if ( s_tlsThisThread == 0xFFFFFFFF )
734 {
735 // in normal circumstances it will only happen if all other
736 // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other
737 // words, this should never happen
738 wxLogSysError(_("Thread module initialization failed: "
739 "impossible to allocate index in thread "
740 "local storage"));
741
742 return FALSE;
743 }
744*/
745 // main thread doesn't have associated wxThread object, so store 0 in the
746 // TLS instead
747
748// TODO:
749/*
750 if ( !::TlsSetValue(s_tlsThisThread, (LPVOID)0) )
751 {
752 ::TlsFree(s_tlsThisThread);
753 s_tlsThisThread = 0xFFFFFFFF;
754
755 wxLogSysError(_("Thread module initialization failed: "
756 "can not store value in thread local storage"));
757
758 return FALSE;
759 }
760*/
761 s_critsectWaitingForGui = new wxCriticalSection();
762
763 s_critsectGui = new wxCriticalSection();
764 s_critsectGui->Enter();
765
766 // no error return for GetCurrentThreadId()
767// s_idMainThread = ::GetCurrentThreadId();
768
769 return TRUE;
770}
771
772void wxThreadModule::OnExit()
773{
774// TODO:
775/*
776 if ( !::TlsFree(s_tlsThisThread) )
777 {
778 wxLogLastError("TlsFree failed.");
779 }
780*/
781 if ( s_critsectGui )
782 {
783 s_critsectGui->Leave();
784 delete s_critsectGui;
785 s_critsectGui = NULL;
786 }
787
788 wxDELETE(s_critsectWaitingForGui);
789}
790
791// ----------------------------------------------------------------------------
792// under Windows, these functions are implemented usign a critical section and
793// not a mutex, so the names are a bit confusing
794// ----------------------------------------------------------------------------
795
796void WXDLLEXPORT wxMutexGuiEnter()
797{
798 // this would dead lock everything...
799 wxASSERT_MSG( !wxThread::IsMain(),
800 wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
801
802 // the order in which we enter the critical sections here is crucial!!
803
804 // set the flag telling to the main thread that we want to do some GUI
805 {
806 wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
807
808 s_nWaitingForGui++;
809 }
810
811 wxWakeUpMainThread();
812
813 // now we may block here because the main thread will soon let us in
814 // (during the next iteration of OnIdle())
815 s_critsectGui->Enter();
816}
817
818void WXDLLEXPORT wxMutexGuiLeave()
819{
820 wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
821
822 if ( wxThread::IsMain() )
823 {
824 s_bGuiOwnedByMainThread = FALSE;
825 }
826 else
827 {
828 // decrement the number of waiters now
829 wxASSERT_MSG( s_nWaitingForGui > 0,
830 wxT("calling wxMutexGuiLeave() without entering it first?") );
831
832 s_nWaitingForGui--;
833
834 wxWakeUpMainThread();
835 }
836
837 s_critsectGui->Leave();
838}
839
840void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
841{
842 wxASSERT_MSG( wxThread::IsMain(),
843 wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
844
845 wxCriticalSectionLocker enter(*s_critsectWaitingForGui);
846
847 if ( s_nWaitingForGui == 0 )
848 {
849 // no threads are waiting for GUI - so we may acquire the lock without
850 // any danger (but only if we don't already have it)
851 if ( !wxGuiOwnedByMainThread() )
852 {
853 s_critsectGui->Enter();
854
855 s_bGuiOwnedByMainThread = TRUE;
856 }
857 //else: already have it, nothing to do
858 }
859 else
860 {
861 // some threads are waiting, release the GUI lock if we have it
862 if ( wxGuiOwnedByMainThread() )
863 {
864 wxMutexGuiLeave();
865 }
866 //else: some other worker thread is doing GUI
867 }
868}
869
870bool WXDLLEXPORT wxGuiOwnedByMainThread()
871{
872 return s_bGuiOwnedByMainThread;
873}
874
875// wake up the main thread if it's in ::GetMessage()
876void WXDLLEXPORT wxWakeUpMainThread()
877{
878 // sending any message would do - hopefully WM_NULL is harmless enough
879// TODO:
880/*
881 if ( !::PostThreadMessage(s_idMainThread, WM_NULL, 0, 0) )
882 {
883 // should never happen
884 wxLogLastError("PostThreadMessage(WM_NULL)");
885 }
886*/
887}
888
889bool WXDLLEXPORT wxIsWaitingForThread()
890{
891 return s_waitingForThread;
892}
893
894
0e320a79
DW
895#endif
896 // wxUSE_THREADS