1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/palmos/thread.cpp
3 // Purpose: wxThread Implementation
4 // Author: William Osborne - minimal working wxPalmOS port
8 // Copyright: (c) William Osborne
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ----------------------------------------------------------------------------
14 // ----------------------------------------------------------------------------
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
19 #if defined(__BORLANDC__)
25 #include "wx/thread.h"
30 #include "wx/module.h"
33 #include "wx/apptrait.h"
35 #include "wx/palmos/private.h"
36 #include "wx/palmos/missing.h"
38 // must have this symbol defined to get _beginthread/_endthread declarations
43 #if defined(__BORLANDC__)
45 // I can't set -tWM in the IDE (anyone?) so have to do this
49 #if !defined(__MFC_COMPAT__)
50 // Needed to know about _beginthreadex etc..
51 #define __MFC_COMPAT__
55 // define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function
56 // which should be used instead of Win32 ::CreateThread() if possible
57 #if defined(__VISUALC__) || \
58 (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \
59 (defined(__GNUG__) && defined(__MSVCRT__)) || \
60 defined(__WATCOMC__) || defined(__MWERKS__)
63 #undef wxUSE_BEGIN_THREAD
64 #define wxUSE_BEGIN_THREAD
69 #ifdef wxUSE_BEGIN_THREAD
70 // the return type of the thread function entry point
71 typedef unsigned THREAD_RETVAL
;
73 // the calling convention of the thread function entry point
74 #define THREAD_CALLCONV __stdcall
76 // the settings for CreateThread()
77 typedef DWORD THREAD_RETVAL
;
78 #define THREAD_CALLCONV WINAPI
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 // the possible states of the thread ("=>" shows all possible transitions from
89 STATE_NEW
, // didn't start execution yet (=> RUNNING)
90 STATE_RUNNING
, // thread is running (=> PAUSED, CANCELED)
91 STATE_PAUSED
, // thread is temporarily suspended (=> RUNNING)
92 STATE_CANCELED
, // thread should terminate a.s.a.p. (=> EXITED)
93 STATE_EXITED
// thread is terminating
96 // ----------------------------------------------------------------------------
97 // this module globals
98 // ----------------------------------------------------------------------------
100 // TLS index of the slot where we store the pointer to the current thread
101 static DWORD gs_tlsThisThread
= 0xFFFFFFFF;
103 // id of the main thread - the one which can call GUI functions without first
104 // calling wxMutexGuiEnter()
105 static DWORD gs_idMainThread
= 0;
107 // if it's false, some secondary thread is holding the GUI lock
108 static bool gs_bGuiOwnedByMainThread
= true;
110 // critical section which controls access to all GUI functions: any secondary
111 // thread (i.e. except the main one) must enter this crit section before doing
113 static wxCriticalSection
*gs_critsectGui
= NULL
;
115 // critical section which protects gs_nWaitingForGui variable
116 static wxCriticalSection
*gs_critsectWaitingForGui
= NULL
;
118 // critical section which serializes WinThreadStart() and WaitForTerminate()
119 // (this is a potential bottleneck, we use a single crit sect for all threads
120 // in the system, but normally time spent inside it should be quite short)
121 static wxCriticalSection
*gs_critsectThreadDelete
= NULL
;
123 // number of threads waiting for GUI in wxMutexGuiEnter()
124 static size_t gs_nWaitingForGui
= 0;
126 // are we waiting for a thread termination?
127 static bool gs_waitingForThread
= false;
129 // ============================================================================
130 // Windows implementation of thread and related classes
131 // ============================================================================
133 // ----------------------------------------------------------------------------
135 // ----------------------------------------------------------------------------
137 wxCriticalSection::wxCriticalSection()
141 wxCriticalSection::~wxCriticalSection()
145 void wxCriticalSection::Enter()
149 bool wxCriticalSection::TryEnter()
154 void wxCriticalSection::Leave()
158 // ----------------------------------------------------------------------------
160 // ----------------------------------------------------------------------------
162 class wxMutexInternal
165 wxMutexInternal(wxMutexType mutexType
);
168 bool IsOk() const { return m_mutex
!= NULL
; }
170 wxMutexError
Lock() { return LockTimeout(INFINITE
); }
171 wxMutexError
TryLock() { return LockTimeout(0); }
172 wxMutexError
Unlock();
175 wxMutexError
LockTimeout(DWORD milliseconds
);
179 wxDECLARE_NO_COPY_CLASS(wxMutexInternal
);
182 // all mutexes are recursive under Win32 so we don't use mutexType
183 wxMutexInternal::wxMutexInternal(wxMutexType
WXUNUSED(mutexType
))
187 wxMutexInternal::~wxMutexInternal()
191 wxMutexError
wxMutexInternal::LockTimeout(DWORD milliseconds
)
193 return wxMUTEX_NO_ERROR
;
196 wxMutexError
wxMutexInternal::Unlock()
198 return wxMUTEX_NO_ERROR
;
201 // --------------------------------------------------------------------------
203 // --------------------------------------------------------------------------
205 // a trivial wrapper around Win32 semaphore
206 class wxSemaphoreInternal
209 wxSemaphoreInternal(int initialcount
, int maxcount
);
210 ~wxSemaphoreInternal();
212 bool IsOk() const { return m_semaphore
!= NULL
; }
214 wxSemaError
Wait() { return WaitTimeout(INFINITE
); }
216 wxSemaError
TryWait()
218 wxSemaError rc
= WaitTimeout(0);
219 if ( rc
== wxSEMA_TIMEOUT
)
225 wxSemaError
WaitTimeout(unsigned long milliseconds
);
232 wxDECLARE_NO_COPY_CLASS(wxSemaphoreInternal
);
235 wxSemaphoreInternal::wxSemaphoreInternal(int initialcount
, int maxcount
)
239 wxSemaphoreInternal::~wxSemaphoreInternal()
243 wxSemaError
wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds
)
245 return wxSEMA_NO_ERROR
;
248 wxSemaError
wxSemaphoreInternal::Post()
250 return wxSEMA_NO_ERROR
;
253 // ----------------------------------------------------------------------------
254 // wxThread implementation
255 // ----------------------------------------------------------------------------
257 // wxThreadInternal class
258 // ----------------------
260 class wxThreadInternal
263 wxThreadInternal(wxThread
*thread
)
268 m_priority
= WXTHREAD_DEFAULT_PRIORITY
;
281 if ( !::CloseHandle(m_hThread
) )
283 wxLogLastError(wxT("CloseHandle(thread)"));
290 // create a new (suspended) thread (for the given thread object)
291 bool Create(wxThread
*thread
, unsigned int stackSize
);
293 // wait for the thread to terminate, either by itself, or by asking it
294 // (politely, this is not Kill()!) to do it
295 wxThreadError
WaitForTerminate(wxCriticalSection
& cs
,
296 wxThread::ExitCode
*pRc
,
297 wxThread
*threadToDelete
= NULL
);
299 // kill the thread unconditionally
300 wxThreadError
Kill();
302 // suspend/resume/terminate
305 void Cancel() { m_state
= STATE_CANCELED
; }
308 void SetState(wxThreadState state
) { m_state
= state
; }
309 wxThreadState
GetState() const { return m_state
; }
312 void SetPriority(unsigned int priority
);
313 unsigned int GetPriority() const { return m_priority
; }
315 // thread handle and id
316 HANDLE
GetHandle() const { return m_hThread
; }
317 DWORD
GetId() const { return m_tid
; }
320 static THREAD_RETVAL THREAD_CALLCONV
WinThreadStart(void *thread
);
324 if ( m_thread
->IsDetached() )
325 ::InterlockedIncrement(&m_nRef
);
330 if ( m_thread
->IsDetached() && !::InterlockedDecrement(&m_nRef
) )
335 // the thread we're associated with
338 HANDLE m_hThread
; // handle of the thread
339 wxThreadState m_state
; // state, see wxThreadState enum
340 unsigned int m_priority
; // thread priority in "wx" units
341 DWORD m_tid
; // thread id
343 // number of threads which need this thread to remain alive, when the count
344 // reaches 0 we kill the owning wxThread -- and die ourselves with it
347 wxDECLARE_NO_COPY_CLASS(wxThreadInternal
);
350 // small class which keeps a thread alive during its lifetime
351 class wxThreadKeepAlive
354 wxThreadKeepAlive(wxThreadInternal
& thrImpl
) : m_thrImpl(thrImpl
)
355 { m_thrImpl
.KeepAlive(); }
357 { m_thrImpl
.LetDie(); }
360 wxThreadInternal
& m_thrImpl
;
364 THREAD_RETVAL THREAD_CALLCONV
wxThreadInternal::WinThreadStart(void *param
)
371 void wxThreadInternal::SetPriority(unsigned int priority
)
375 bool wxThreadInternal::Create(wxThread
*thread
, unsigned int stackSize
)
380 wxThreadError
wxThreadInternal::Kill()
382 return wxTHREAD_NO_ERROR
;
386 wxThreadInternal::WaitForTerminate(wxCriticalSection
& cs
,
387 wxThread::ExitCode
*pRc
,
388 wxThread
*threadToDelete
)
390 return wxTHREAD_NO_ERROR
;
393 bool wxThreadInternal::Suspend()
398 bool wxThreadInternal::Resume()
406 wxThread
*wxThread::This()
411 bool wxThread::IsMain()
416 void wxThread::Yield()
420 int wxThread::GetCPUCount()
425 unsigned long wxThread::GetCurrentId()
430 bool wxThread::SetConcurrency(size_t level
)
438 wxThread::wxThread(wxThreadKind kind
)
442 wxThread::~wxThread()
446 // create/start thread
447 // -------------------
449 wxThreadError
wxThread::Create(unsigned int stackSize
)
451 return wxTHREAD_NO_ERROR
;
454 wxThreadError
wxThread::Run()
456 return wxTHREAD_RUNNING
;
459 // suspend/resume thread
460 // ---------------------
462 wxThreadError
wxThread::Pause()
464 return wxTHREAD_NO_ERROR
;
467 wxThreadError
wxThread::Resume()
469 return wxTHREAD_NO_ERROR
;
475 wxThread::ExitCode
wxThread::Wait(wxThreadWait
WXUNUSED(waitMode
))
480 wxThreadError
wxThread::Delete(ExitCode
*pRc
, wxThreadWait
WXUNUSED(waitMode
))
482 return wxTHREAD_NO_ERROR
;
485 wxThreadError
wxThread::Kill()
487 return wxTHREAD_NO_ERROR
;
490 void wxThread::Exit(ExitCode status
)
497 void wxThread::SetPriority(unsigned int prio
)
501 unsigned int wxThread::GetPriority() const
506 unsigned long wxThread::GetId() const
511 bool wxThread::IsRunning() const
516 bool wxThread::IsAlive() const
521 bool wxThread::IsPaused() const
526 bool wxThread::TestDestroy()
531 // ----------------------------------------------------------------------------
532 // Automatic initialization for thread module
533 // ----------------------------------------------------------------------------
535 class wxThreadModule
: public wxModule
538 virtual bool OnInit();
539 virtual void OnExit();
542 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
545 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
547 bool wxThreadModule::OnInit()
552 void wxThreadModule::OnExit()
556 // ----------------------------------------------------------------------------
557 // under Windows, these functions are implemented using a critical section and
558 // not a mutex, so the names are a bit confusing
559 // ----------------------------------------------------------------------------
561 void wxMutexGuiEnterImpl()
565 void wxMutexGuiLeaveImpl()
569 void WXDLLIMPEXP_BASE
wxMutexGuiLeaveOrEnter()
573 bool WXDLLIMPEXP_BASE
wxGuiOwnedByMainThread()
578 // wake up the main thread if it's in ::GetMessage()
579 void WXDLLIMPEXP_BASE
wxWakeUpMainThread()
583 bool WXDLLIMPEXP_BASE
wxIsWaitingForThread()
588 // ----------------------------------------------------------------------------
589 // include common implementation code
590 // ----------------------------------------------------------------------------
592 #include "wx/thrimpl.cpp"
594 #endif // wxUSE_THREADS