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 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #if defined(__BORLANDC__)
37 #include "wx/module.h"
38 #include "wx/thread.h"
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // id of the main thread - the one which can call GUI functions without first
53 // calling wxMutexGuiEnter()
54 static HANDLE s_idMainThread
;
56 // critical section which controls access to all GUI functions: any secondary
57 // thread (i.e. except the main one) must enter this crit section before doing
59 static wxCriticalSection
*s_critsectGui
;
61 // ============================================================================
62 // Windows implementation of thread classes
63 // ============================================================================
65 // ----------------------------------------------------------------------------
66 // wxMutex implementation
67 // ----------------------------------------------------------------------------
76 p_internal
= new wxMutexInternal
;
77 p_internal
->p_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
78 if ( !p_internal
->p_mutex
)
80 wxLogSysError(_("Can not create mutex."));
89 wxLogDebug("Warning: freeing a locked mutex (%d locks).", m_locked
);
90 CloseHandle(p_internal
->p_mutex
);
93 wxMutexError
wxMutex::Lock()
97 ret
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
);
108 wxLogSysError(_("Couldn't acquire a mutex lock"));
109 return wxMUTEX_MISC_ERROR
;
113 wxFAIL_MSG("impossible return value in wxMutex::Lock");
117 return wxMUTEX_NO_ERROR
;
120 wxMutexError
wxMutex::TryLock()
124 ret
= WaitForSingleObject(p_internal
->p_mutex
, 0);
125 if (ret
== WAIT_TIMEOUT
|| ret
== WAIT_ABANDONED
)
129 return wxMUTEX_NO_ERROR
;
132 wxMutexError
wxMutex::Unlock()
137 BOOL ret
= ReleaseMutex(p_internal
->p_mutex
);
140 wxLogSysError(_("Couldn't release a mutex"));
141 return wxMUTEX_MISC_ERROR
;
144 return wxMUTEX_NO_ERROR
;
147 // ----------------------------------------------------------------------------
148 // wxCondition implementation
149 // ----------------------------------------------------------------------------
151 class wxConditionInternal
158 wxCondition::wxCondition()
160 p_internal
= new wxConditionInternal
;
161 p_internal
->event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
162 if ( !p_internal
->event
)
164 wxLogSysError(_("Can not create event object."));
167 p_internal
->waiters
= 0;
170 wxCondition::~wxCondition()
172 CloseHandle(p_internal
->event
);
175 void wxCondition::Wait(wxMutex
& mutex
)
178 p_internal
->waiters
++;
179 WaitForSingleObject(p_internal
->event
, INFINITE
);
180 p_internal
->waiters
--;
184 bool wxCondition::Wait(wxMutex
& mutex
,
191 p_internal
->waiters
++;
192 ret
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000));
193 p_internal
->waiters
--;
196 return (ret
!= WAIT_TIMEOUT
);
199 void wxCondition::Signal()
201 SetEvent(p_internal
->event
);
204 void wxCondition::Broadcast()
208 for (i
=0;i
<p_internal
->waiters
;i
++)
210 if ( SetEvent(p_internal
->event
) == 0 )
212 wxLogSysError(_("Couldn't change the state of event object."));
217 // ----------------------------------------------------------------------------
218 // wxCriticalSection implementation
219 // ----------------------------------------------------------------------------
221 class wxCriticalSectionInternal
224 // init the critical section object
225 wxCriticalSectionInternal()
226 { ::InitializeCriticalSection(&m_data
); }
228 // implicit cast to the associated data
229 operator CRITICAL_SECTION
*() { return &m_data
; }
231 // free the associated ressources
232 ~wxCriticalSectionInternal()
233 { ::DeleteCriticalSection(&m_data
); }
236 CRITICAL_SECTION m_data
;
239 wxCriticalSection::wxCriticalSection()
241 m_critsect
= new wxCriticalSectionInternal
;
244 wxCriticalSection::~wxCriticalSection()
249 void wxCriticalSection::Enter()
251 ::EnterCriticalSection(*m_critsect
);
254 void wxCriticalSection::Leave()
256 ::LeaveCriticalSection(*m_critsect
);
259 // ----------------------------------------------------------------------------
260 // wxThread implementation
261 // ----------------------------------------------------------------------------
263 class wxThreadInternal
266 static DWORD
WinThreadStart(LPVOID arg
);
274 DWORD
wxThreadInternal::WinThreadStart(LPVOID arg
)
276 wxThread
*ptr
= (wxThread
*)arg
;
279 ret
= (DWORD
)ptr
->Entry();
280 ptr
->p_internal
->state
= STATE_EXITED
;
285 wxThreadError
wxThread::Create()
287 int prio
= p_internal
->prio
;
289 p_internal
->thread_id
= CreateThread(NULL
, 0,
290 (LPTHREAD_START_ROUTINE
)wxThreadInternal::WinThreadStart
,
291 (void *)this, CREATE_SUSPENDED
, &p_internal
->tid
);
293 if ( p_internal
->thread_id
== NULL
)
295 wxLogSysError(_("Can't create thread"));
296 return wxTHREAD_NO_RESOURCE
;
301 win_prio
= THREAD_PRIORITY_LOWEST
;
303 win_prio
= THREAD_PRIORITY_BELOW_NORMAL
;
305 win_prio
= THREAD_PRIORITY_NORMAL
;
307 win_prio
= THREAD_PRIORITY_ABOVE_NORMAL
;
308 else if (prio
<= 100)
309 win_prio
= THREAD_PRIORITY_HIGHEST
;
312 wxFAIL_MSG("invalid value of thread priority parameter");
313 win_prio
= THREAD_PRIORITY_NORMAL
;
316 SetThreadPriority(p_internal
->thread_id
, win_prio
);
318 ResumeThread(p_internal
->thread_id
);
319 p_internal
->state
= STATE_RUNNING
;
321 return wxTHREAD_NO_ERROR
;
324 wxThreadError
wxThread::Destroy()
326 if (p_internal
->state
!= STATE_RUNNING
)
327 return wxTHREAD_NOT_RUNNING
;
329 if ( p_internal
->defer
)
330 // soft termination: just set the flag and wait until the thread
332 p_internal
->state
= STATE_CANCELED
;
335 TerminateThread(p_internal
->thread_id
, 0);
337 return wxTHREAD_NO_ERROR
;
340 wxThreadError
wxThread::Pause()
342 DWORD nSuspendCount
= ::SuspendThread(p_internal
->thread_id
);
343 if ( nSuspendCount
== (DWORD
)-1 )
345 wxLogSysError(_("Can not suspend thread %x"), p_internal
->thread_id
);
347 return wxTHREAD_MISC_ERROR
; // no idea what might provoke this error...
350 return wxTHREAD_NO_ERROR
;
353 wxThreadError
wxThread::Resume()
355 DWORD nSuspendCount
= ::ResumeThread(p_internal
->thread_id
);
356 if ( nSuspendCount
== (DWORD
)-1 )
358 wxLogSysError(_("Can not resume thread %x"), p_internal
->thread_id
);
360 return wxTHREAD_MISC_ERROR
; // no idea what might provoke this error...
363 return wxTHREAD_NO_ERROR
;
366 void wxThread::Exit(void *status
)
368 p_internal
->state
= STATE_EXITED
;
369 ExitThread((DWORD
)status
);
372 void wxThread::SetPriority(int prio
)
374 p_internal
->prio
= prio
;
377 int wxThread::GetPriority() const
379 return p_internal
->prio
;
382 void wxThread::DeferDestroy(bool on
)
384 p_internal
->defer
= on
;
387 bool wxThread::TestDestroy()
389 return p_internal
->state
== STATE_CANCELED
;
392 void *wxThread::Join()
396 if (p_internal
->state
== STATE_IDLE
)
399 if (wxThread::IsMain())
400 s_critsectGui
->Leave();
401 WaitForSingleObject(p_internal
->thread_id
, INFINITE
);
402 if (wxThread::IsMain())
403 s_critsectGui
->Enter();
405 GetExitCodeThread(p_internal
->thread_id
, &exit_code
);
406 CloseHandle(p_internal
->thread_id
);
408 p_internal
->state
= STATE_IDLE
;
410 return (void *)exit_code
;
413 unsigned long wxThread::GetID() const
415 return (unsigned long)p_internal
->tid
;
418 bool wxThread::IsRunning() const
420 return (p_internal
->state
== STATE_RUNNING
);
423 bool wxThread::IsAlive() const
425 return (p_internal
->state
== STATE_RUNNING
);
428 bool wxThread::IsMain()
430 return (GetCurrentThread() == s_idMainThread
);
435 p_internal
= new wxThreadInternal();
437 p_internal
->defer
= FALSE
;
438 p_internal
->prio
= WXTHREAD_DEFAULT_PRIORITY
;
439 p_internal
->state
= STATE_IDLE
;
442 wxThread::~wxThread()
449 void wxThread::OnExit()
453 // ----------------------------------------------------------------------------
454 // Automatic initialization for thread module
455 // ----------------------------------------------------------------------------
457 class wxThreadModule
: public wxModule
460 virtual bool OnInit();
461 virtual void OnExit();
464 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
467 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
469 bool wxThreadModule::OnInit()
471 s_critsectGui
= new wxCriticalSection();
472 s_critsectGui
->Enter();
473 s_idMainThread
= GetCurrentThread();
478 void wxThreadModule::OnExit()
482 s_critsectGui
->Leave();
483 delete s_critsectGui
;
484 s_critsectGui
= NULL
;
488 // under Windows, these functions are implemented usign a critical section and
489 // not a mutex, so the names are a bit confusing
490 void WXDLLEXPORT
wxMutexGuiEnter()
492 //s_critsectGui->Enter();
495 void WXDLLEXPORT
wxMutexGuiLeave()
497 //s_critsectGui->Leave();
500 #endif // wxUSE_THREADS