1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "thread.h"
16 // this is here to regen the precompiled header in the ide compile otherwise the
17 // compiler crashes in vc5 (nfi why)
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
21 #if defined(__BORLANDC__)
32 #include "wx/module.h"
33 #include "wx/thread.h"
42 /////////////////////////////////////////////////////////////////////////////
44 /////////////////////////////////////////////////////////////////////////////
46 static HANDLE p_mainid
;
47 wxMutex
*wxMainMutex
; // controls access to all GUI functions
49 /////////////////////////////////////////////////////////////////////////////
50 // Windows implementation
51 /////////////////////////////////////////////////////////////////////////////
53 class wxMutexInternal
{
60 p_internal
= new wxMutexInternal
;
61 p_internal
->p_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
62 if ( !p_internal
->p_mutex
)
64 wxLogSysError(_("Can not create mutex."));
73 wxLogDebug("Warning: freeing a locked mutex (%d locks).", m_locked
);
74 CloseHandle(p_internal
->p_mutex
);
77 wxMutexError
wxMutex::Lock()
81 ret
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
);
82 if (ret
== WAIT_ABANDONED
)
86 return wxMUTEX_NO_ERROR
;
89 wxMutexError
wxMutex::TryLock()
93 ret
= WaitForSingleObject(p_internal
->p_mutex
, 0);
94 if (ret
== WAIT_TIMEOUT
|| ret
== WAIT_ABANDONED
)
98 return wxMUTEX_NO_ERROR
;
101 wxMutexError
wxMutex::Unlock()
106 BOOL ret
= ReleaseMutex(p_internal
->p_mutex
);
109 wxLogSysError(_("Couldn't release a mutex"));
110 return wxMUTEX_MISC_ERROR
;
113 return wxMUTEX_NO_ERROR
;
116 class wxConditionInternal
{
122 wxCondition::wxCondition()
124 p_internal
= new wxConditionInternal
;
125 p_internal
->event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
126 if ( !p_internal
->event
)
128 wxLogSysError(_("Can not create event object."));
131 p_internal
->waiters
= 0;
134 wxCondition::~wxCondition()
136 CloseHandle(p_internal
->event
);
139 void wxCondition::Wait(wxMutex
& mutex
)
142 p_internal
->waiters
++;
143 WaitForSingleObject(p_internal
->event
, INFINITE
);
144 p_internal
->waiters
--;
148 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
,
154 p_internal
->waiters
++;
155 ret
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000));
156 p_internal
->waiters
--;
159 return (ret
!= WAIT_TIMEOUT
);
162 void wxCondition::Signal()
164 SetEvent(p_internal
->event
);
167 void wxCondition::Broadcast()
171 for (i
=0;i
<p_internal
->waiters
;i
++)
173 if ( SetEvent(p_internal
->event
) == 0 )
175 wxLogSysError(_("Couldn't change the state of event object."));
180 class wxThreadInternal
{
182 static DWORD
WinThreadStart(LPVOID arg
);
190 DWORD
wxThreadInternal::WinThreadStart(LPVOID arg
)
192 wxThread
*ptr
= (wxThread
*)arg
;
195 ret
= (DWORD
)ptr
->Entry();
196 ptr
->p_internal
->state
= STATE_EXITED
;
201 wxThreadError
wxThread::Create()
203 int prio
= p_internal
->prio
;
205 p_internal
->thread_id
= CreateThread(NULL
, 0,
206 (LPTHREAD_START_ROUTINE
)wxThreadInternal::WinThreadStart
,
207 (void *)this, CREATE_SUSPENDED
, &p_internal
->tid
);
209 if ( p_internal
->thread_id
== NULL
)
211 wxLogSysError(_("Can't create thread"));
212 return wxTHREAD_NO_RESOURCE
;
217 win_prio
= THREAD_PRIORITY_LOWEST
;
219 win_prio
= THREAD_PRIORITY_BELOW_NORMAL
;
221 win_prio
= THREAD_PRIORITY_NORMAL
;
223 win_prio
= THREAD_PRIORITY_ABOVE_NORMAL
;
224 else if (prio
<= 100)
225 win_prio
= THREAD_PRIORITY_HIGHEST
;
228 wxFAIL_MSG("invalid value of thread priority parameter");
229 win_prio
= THREAD_PRIORITY_NORMAL
;
232 SetThreadPriority(p_internal
->thread_id
, win_prio
);
234 ResumeThread(p_internal
->thread_id
);
235 p_internal
->state
= STATE_RUNNING
;
237 return wxTHREAD_NO_ERROR
;
240 wxThreadError
wxThread::Destroy()
242 if (p_internal
->state
!= STATE_RUNNING
)
243 return wxTHREAD_NOT_RUNNING
;
245 if (p_internal
->defer
== FALSE
)
246 TerminateThread(p_internal
->thread_id
, 0);
248 p_internal
->state
= STATE_CANCELED
;
250 return wxTHREAD_NO_ERROR
;
253 wxThreadError
wxThread::Pause()
255 DWORD nSuspendCount
= ::SuspendThread(p_internal
->thread_id
);
256 if ( nSuspendCount
== (DWORD
)-1 )
258 wxLogSysError(_("Can not suspend thread %x"), p_internal
->thread_id
);
260 return wxTHREAD_MISC_ERROR
; // no idea what might provoke this error...
263 return wxTHREAD_NO_ERROR
;
266 wxThreadError
wxThread::Resume()
268 DWORD nSuspendCount
= ::ResumeThread(p_internal
->thread_id
);
269 if ( nSuspendCount
== (DWORD
)-1 )
271 wxLogSysError(_("Can not resume thread %x"), p_internal
->thread_id
);
273 return wxTHREAD_MISC_ERROR
; // no idea what might provoke this error...
276 return wxTHREAD_NO_ERROR
;
279 void wxThread::Exit(void *status
)
281 p_internal
->state
= STATE_EXITED
;
282 ExitThread((DWORD
)status
);
285 void wxThread::SetPriority(int prio
)
287 p_internal
->prio
= prio
;
290 int wxThread::GetPriority() const
292 return p_internal
->prio
;
295 void wxThread::DeferDestroy(bool on
)
297 p_internal
->defer
= on
;
300 void wxThread::TestDestroy()
302 if (p_internal
->state
== STATE_CANCELED
)
306 void *wxThread::Join()
310 if (p_internal
->state
== STATE_IDLE
)
313 if (wxThread::IsMain())
314 wxMainMutex
->Unlock();
315 WaitForSingleObject(p_internal
->thread_id
, INFINITE
);
316 if (wxThread::IsMain())
319 GetExitCodeThread(p_internal
->thread_id
, &exit_code
);
320 CloseHandle(p_internal
->thread_id
);
322 p_internal
->state
= STATE_IDLE
;
324 return (void *)exit_code
;
327 unsigned long wxThread::GetID() const
329 return (unsigned long)p_internal
->tid
;
332 bool wxThread::IsRunning() const
334 return (p_internal
->state
== STATE_RUNNING
);
337 bool wxThread::IsAlive() const
339 return (p_internal
->state
== STATE_RUNNING
);
342 bool wxThread::IsMain()
344 return (GetCurrentThread() == p_mainid
);
349 p_internal
= new wxThreadInternal();
351 p_internal
->defer
= FALSE
;
352 p_internal
->prio
= WXTHREAD_DEFAULT_PRIORITY
;
353 p_internal
->state
= STATE_IDLE
;
356 wxThread::~wxThread()
363 // The default callback just joins the thread and throws away the result.
364 void wxThread::OnExit()
369 // Automatic initialization
370 class wxThreadModule
: public wxModule
{
371 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
373 virtual bool OnInit() {
374 wxMainMutex
= new wxMutex();
375 p_mainid
= GetCurrentThread();
381 virtual void OnExit() {
382 wxMainMutex
->Unlock();
387 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
389 void WXDLLEXPORT
wxMutexGuiEnter()
391 wxFAIL_MSG("not implemented");
394 void WXDLLEXPORT
wxMutexGuiLeave()
396 wxFAIL_MSG("not implemented");