1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/palmos/thread.cpp
3 // Purpose: wxThread Implementation
4 // Author: William Osborne
8 // Copyright: (c) William Osborne
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "thread.h"
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #if defined(__BORLANDC__)
34 #include "wx/apptrait.h"
36 #include "wx/palmos/private.h"
37 #include "wx/palmos/missing.h"
39 #include "wx/module.h"
40 #include "wx/thread.h"
42 // must have this symbol defined to get _beginthread/_endthread declarations
47 #if defined(__BORLANDC__)
49 // I can't set -tWM in the IDE (anyone?) so have to do this
53 #if !defined(__MFC_COMPAT__)
54 // Needed to know about _beginthreadex etc..
55 #define __MFC_COMPAT__
59 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function
60 // which should be used instead of Win32 ::CreateThread() if possible
61 #if defined(__VISUALC__) || \
62 (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \
63 (defined(__GNUG__) && defined(__MSVCRT__)) || \
64 defined(__WATCOMC__) || defined(__MWERKS__)
67 #undef wxUSE_BEGIN_THREAD
68 #define wxUSE_BEGIN_THREAD
73 #ifdef wxUSE_BEGIN_THREAD
74 // the return type of the thread function entry point
75 typedef unsigned THREAD_RETVAL
;
77 // the calling convention of the thread function entry point
78 #define THREAD_CALLCONV __stdcall
80 // the settings for CreateThread()
81 typedef DWORD THREAD_RETVAL
;
82 #define THREAD_CALLCONV WINAPI
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
89 // the possible states of the thread ("=>" shows all possible transitions from
93 STATE_NEW
, // didn't start execution yet (=> RUNNING)
94 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
95 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
96 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
97 STATE_EXITED
// thread is terminating
100 // ----------------------------------------------------------------------------
101 // this module globals
102 // ----------------------------------------------------------------------------
104 // TLS index of the slot where we store the pointer to the current thread
105 static DWORD gs_tlsThisThread
= 0xFFFFFFFF;
107 // id of the main thread - the one which can call GUI functions without first
108 // calling wxMutexGuiEnter()
109 static DWORD gs_idMainThread
= 0;
111 // if it's false, some secondary thread is holding the GUI lock
112 static bool gs_bGuiOwnedByMainThread
= true;
114 // critical section which controls access to all GUI functions: any secondary
115 // thread (i.e. except the main one) must enter this crit section before doing
117 static wxCriticalSection
*gs_critsectGui
= NULL
;
119 // critical section which protects gs_nWaitingForGui variable
120 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
122 // critical section which serializes WinThreadStart() and WaitForTerminate()
123 // (this is a potential bottleneck, we use a single crit sect for all threads
124 // in the system, but normally time spent inside it should be quite short)
125 static wxCriticalSection
*gs_critsectThreadDelete
= NULL
;
127 // number of threads waiting for GUI in wxMutexGuiEnter()
128 static size_t gs_nWaitingForGui
= 0;
130 // are we waiting for a thread termination?
131 static bool gs_waitingForThread
= false;
133 // ============================================================================
134 // Windows implementation of thread and related classes
135 // ============================================================================
137 // ----------------------------------------------------------------------------
139 // ----------------------------------------------------------------------------
141 wxCriticalSection::wxCriticalSection()
145 wxCriticalSection::~wxCriticalSection()
149 void wxCriticalSection::Enter()
153 void wxCriticalSection::Leave()
157 // ----------------------------------------------------------------------------
159 // ----------------------------------------------------------------------------
161 class wxMutexInternal
164 wxMutexInternal(wxMutexType mutexType
);
167 bool IsOk() const { return m_mutex
!= NULL
; }
169 wxMutexError
Lock() { return LockTimeout(INFINITE
); }
170 wxMutexError
TryLock() { return LockTimeout(0); }
171 wxMutexError
Unlock();
174 wxMutexError
LockTimeout(DWORD milliseconds
);
178 DECLARE_NO_COPY_CLASS(wxMutexInternal
)
181 // all mutexes are recursive under Win32 so we don't use mutexType
182 wxMutexInternal::wxMutexInternal(wxMutexType
WXUNUSED(mutexType
))
186 wxMutexInternal::~wxMutexInternal()
190 wxMutexError
wxMutexInternal::LockTimeout(DWORD milliseconds
)
192 return wxMUTEX_NO_ERROR
;
195 wxMutexError
wxMutexInternal::Unlock()
197 return wxMUTEX_NO_ERROR
;
200 // --------------------------------------------------------------------------
202 // --------------------------------------------------------------------------
204 // a trivial wrapper around Win32 semaphore
205 class wxSemaphoreInternal
208 wxSemaphoreInternal(int initialcount
, int maxcount
);
209 ~wxSemaphoreInternal();
211 bool IsOk() const { return m_semaphore
!= NULL
; }
213 wxSemaError
Wait() { return WaitTimeout(INFINITE
); }
215 wxSemaError
TryWait()
217 wxSemaError rc
= WaitTimeout(0);
218 if ( rc
== wxSEMA_TIMEOUT
)
224 wxSemaError
WaitTimeout(unsigned long milliseconds
);
231 DECLARE_NO_COPY_CLASS(wxSemaphoreInternal
)
234 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
238 wxSemaphoreInternal::~wxSemaphoreInternal()
242 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
244 return wxSEMA_NO_ERROR
;
247 wxSemaError
wxSemaphoreInternal::Post()
249 return wxSEMA_NO_ERROR
;
252 // ----------------------------------------------------------------------------
253 // wxThread implementation
254 // ----------------------------------------------------------------------------
256 // wxThreadInternal class
257 // ----------------------
259 class wxThreadInternal
262 wxThreadInternal(wxThread
*thread
)
267 m_priority
= WXTHREAD_DEFAULT_PRIORITY
;
280 if ( !::CloseHandle(m_hThread
) )
282 wxLogLastError(wxT("CloseHandle(thread)"));
289 // create a new (suspended) thread (for the given thread object)
290 bool Create(wxThread
*thread
, unsigned int stackSize
);
292 // wait for the thread to terminate, either by itself, or by asking it
293 // (politely, this is not Kill()!) to do it
294 wxThreadError
WaitForTerminate(wxCriticalSection
& cs
,
295 wxThread::ExitCode
*pRc
,
296 wxThread
*threadToDelete
= NULL
);
298 // kill the thread unconditionally
299 wxThreadError
Kill();
301 // suspend/resume/terminate
304 void Cancel() { m_state
= STATE_CANCELED
; }
307 void SetState(wxThreadState state
) { m_state
= state
; }
308 wxThreadState
GetState() const { return m_state
; }
311 void SetPriority(unsigned int priority
);
312 unsigned int GetPriority() const { return m_priority
; }
314 // thread handle and id
315 HANDLE
GetHandle() const { return m_hThread
; }
316 DWORD
GetId() const { return m_tid
; }
319 static THREAD_RETVAL THREAD_CALLCONV
WinThreadStart(void *thread
);
323 if ( m_thread
->IsDetached() )
324 ::InterlockedIncrement(&m_nRef
);
329 if ( m_thread
->IsDetached() && !::InterlockedDecrement(&m_nRef
) )
334 // the thread we're associated with
337 HANDLE m_hThread
; // handle of the thread
338 wxThreadState m_state
; // state, see wxThreadState enum
339 unsigned int m_priority
; // thread priority in "wx" units
340 DWORD m_tid
; // thread id
342 // number of threads which need this thread to remain alive, when the count
343 // reaches 0 we kill the owning wxThread -- and die ourselves with it
346 DECLARE_NO_COPY_CLASS(wxThreadInternal
)
349 // small class which keeps a thread alive during its lifetime
350 class wxThreadKeepAlive
353 wxThreadKeepAlive(wxThreadInternal
& thrImpl
) : m_thrImpl(thrImpl
)
354 { m_thrImpl
.KeepAlive(); }
356 { m_thrImpl
.LetDie(); }
359 wxThreadInternal
& m_thrImpl
;
363 THREAD_RETVAL THREAD_CALLCONV
wxThreadInternal::WinThreadStart(void *param
)
370 void wxThreadInternal::SetPriority(unsigned int priority
)
374 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
379 wxThreadError
wxThreadInternal::Kill()
381 return wxTHREAD_NO_ERROR
;
385 wxThreadInternal::WaitForTerminate(wxCriticalSection
& cs
,
386 wxThread::ExitCode
*pRc
,
387 wxThread
*threadToDelete
)
389 return wxTHREAD_NO_ERROR
;
392 bool wxThreadInternal::Suspend()
397 bool wxThreadInternal::Resume()
405 wxThread
*wxThread::This()
410 bool wxThread::IsMain()
415 void wxThread::Yield()
419 void wxThread::Sleep(unsigned long milliseconds
)
423 int wxThread::GetCPUCount()
428 unsigned long wxThread::GetCurrentId()
433 bool wxThread::SetConcurrency(size_t level
)
441 wxThread::wxThread(wxThreadKind kind
)
445 wxThread::~wxThread()
449 // create/start thread
450 // -------------------
452 wxThreadError
wxThread::Create(unsigned int stackSize
)
454 return wxTHREAD_NO_ERROR
;
457 wxThreadError
wxThread::Run()
459 return wxTHREAD_RUNNING
;
462 // suspend/resume thread
463 // ---------------------
465 wxThreadError
wxThread::Pause()
467 return wxTHREAD_NO_ERROR
;
470 wxThreadError
wxThread::Resume()
472 return wxTHREAD_NO_ERROR
;
478 wxThread::ExitCode
wxThread::Wait()
483 wxThreadError
wxThread::Delete(ExitCode
*pRc
)
485 return wxTHREAD_NO_ERROR
;
488 wxThreadError
wxThread::Kill()
490 return wxTHREAD_NO_ERROR
;
493 void wxThread::Exit(ExitCode status
)
500 void wxThread::SetPriority(unsigned int prio
)
504 unsigned int wxThread::GetPriority() const
509 unsigned long wxThread::GetId() const
514 bool wxThread::IsRunning() const
519 bool wxThread::IsAlive() const
524 bool wxThread::IsPaused() const
529 bool wxThread::TestDestroy()
534 // ----------------------------------------------------------------------------
535 // Automatic initialization for thread module
536 // ----------------------------------------------------------------------------
538 class wxThreadModule
: public wxModule
541 virtual bool OnInit();
542 virtual void OnExit();
545 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
548 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
550 bool wxThreadModule::OnInit()
555 void wxThreadModule::OnExit()
559 // ----------------------------------------------------------------------------
560 // under Windows, these functions are implemented using a critical section and
561 // not a mutex, so the names are a bit confusing
562 // ----------------------------------------------------------------------------
564 void WXDLLIMPEXP_BASE
wxMutexGuiEnter()
568 void WXDLLIMPEXP_BASE
wxMutexGuiLeave()
572 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
576 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
581 // wake up the main thread if it's in ::GetMessage()
582 void WXDLLIMPEXP_BASE
wxWakeUpMainThread()
586 bool WXDLLIMPEXP_BASE
wxIsWaitingForThread()
591 // ----------------------------------------------------------------------------
592 // include common implementation code
593 // ----------------------------------------------------------------------------
595 #include "wx/thrimpl.cpp"
597 #endif // wxUSE_THREADS