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 #include "wx/wxprec.h" 
  18 #if defined(__BORLANDC__) 
  29 #include "wx/module.h" 
  30 #include "wx/thread.h" 
  39 ///////////////////////////////////////////////////////////////////////////// 
  41 ///////////////////////////////////////////////////////////////////////////// 
  43 static HANDLE p_mainid
; 
  44 wxMutex wxMainMutex
; // controls access to all GUI functions 
  46 ///////////////////////////////////////////////////////////////////////////// 
  47 // Windows implementation 
  48 ///////////////////////////////////////////////////////////////////////////// 
  50 class wxMutexInternal 
{ 
  55 wxMutex::wxMutex(void) 
  57   p_internal 
= new wxMutexInternal
; 
  58   p_internal
->p_mutex 
= CreateMutex(NULL
, FALSE
, NULL
); 
  62 wxMutex::~wxMutex(void) 
  64   CloseHandle(p_internal
->p_mutex
); 
  67 wxMutexError 
wxMutex::Lock(void) 
  71   ret 
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
); 
  72   if (ret 
== WAIT_ABANDONED
) 
  76   return MUTEX_NO_ERROR
; 
  79 wxMutexError 
wxMutex::TryLock(void) 
  83   ret 
= WaitForSingleObject(p_internal
->p_mutex
, 0); 
  84   if (ret 
== WAIT_TIMEOUT 
|| ret 
== WAIT_ABANDONED
) 
  88   return MUTEX_NO_ERROR
; 
  91 wxMutexError 
wxMutex::Unlock(void) 
  98     // Why does this have 3 args? The redundant ones removed by JACS 
  99 //  ret = ReleaseMutex(p_internal->p_mutex, 1, NULL); 
 100   ret 
= ReleaseMutex(p_internal
->p_mutex
); 
 101   return MUTEX_NO_ERROR
; 
 104 class wxConditionInternal 
{ 
 110 wxCondition::wxCondition(void) 
 112   p_internal 
= new wxConditionInternal
; 
 113   p_internal
->event 
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
); 
 114   p_internal
->waiters 
= 0; 
 117 wxCondition::~wxCondition(void) 
 119   CloseHandle(p_internal
->event
); 
 122 void wxCondition::Wait(wxMutex
& mutex
) 
 125   p_internal
->waiters
++; 
 126   WaitForSingleObject(p_internal
->event
, INFINITE
); 
 127   p_internal
->waiters
--; 
 131 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, 
 137   p_internal
->waiters
++; 
 138   ret 
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000)); 
 139   p_internal
->waiters
--; 
 142   return (ret 
!= WAIT_TIMEOUT
); 
 145 void wxCondition::Signal(void) 
 147   SetEvent(p_internal
->event
); 
 150 void wxCondition::Broadcast(void) 
 154   for (i
=0;i
<p_internal
->waiters
;i
++) 
 155     SetEvent(p_internal
->event
); 
 158 class wxThreadInternal 
{ 
 160   static DWORD 
WinThreadStart(LPVOID arg
); 
 168 DWORD 
wxThreadInternal::WinThreadStart(LPVOID arg
) 
 170   wxThread 
*ptr 
= (wxThread 
*)arg
; 
 173   ret 
= (DWORD
)ptr
->Entry(); 
 174   ptr
->p_internal
->state 
= STATE_EXITED
; 
 179 wxThreadError 
wxThread::Create(void) 
 181   int win_prio
, prio 
= p_internal
->prio
; 
 183   p_internal
->thread_id 
= CreateThread(NULL
, 0, 
 184                    (LPTHREAD_START_ROUTINE
)wxThreadInternal::WinThreadStart
, 
 185                    (void *)this, CREATE_SUSPENDED
, &p_internal
->tid
); 
 186   if (p_internal
->thread_id 
== NULL
) { 
 187     printf("Error = %d\n", GetLastError()); 
 188     return THREAD_NO_RESOURCE
; 
 192     win_prio 
= THREAD_PRIORITY_LOWEST
; 
 194     win_prio 
= THREAD_PRIORITY_BELOW_NORMAL
; 
 196     win_prio 
= THREAD_PRIORITY_NORMAL
; 
 198     win_prio 
= THREAD_PRIORITY_ABOVE_NORMAL
; 
 199   else if (prio 
<= 100) 
 200     win_prio 
= THREAD_PRIORITY_HIGHEST
; 
 202   SetThreadPriority(p_internal
->thread_id
, win_prio
); 
 204   ResumeThread(p_internal
->thread_id
); 
 205   p_internal
->state 
= STATE_RUNNING
; 
 207   return THREAD_NO_ERROR
; 
 210 wxThreadError 
wxThread::Destroy() 
 212   if (p_internal
->state 
!= STATE_RUNNING
) 
 213     return THREAD_NOT_RUNNING
; 
 215   if (p_internal
->defer 
== FALSE
) 
 216     TerminateThread(p_internal
->thread_id
, 0); 
 218     p_internal
->state 
= STATE_CANCELED
; 
 220   return THREAD_NO_ERROR
; 
 223 void wxThread::Exit(void *status
) 
 225   p_internal
->state 
= STATE_EXITED
; 
 226   ExitThread((DWORD
)status
); 
 229 void wxThread::SetPriority(int prio
) 
 231   p_internal
->prio 
= prio
; 
 234 int wxThread::GetPriority(void) 
 236   return p_internal
->prio
; 
 239 void wxThread::DeferDestroy(bool on
) 
 241   p_internal
->defer 
= on
; 
 244 void wxThread::TestDestroy() 
 246   if (p_internal
->state 
== STATE_CANCELED
) 
 250 void *wxThread::Join() 
 254   if (p_internal
->state 
== STATE_IDLE
) 
 257   if (wxThread::IsMain()) 
 258     wxMainMutex
.Unlock(); 
 259   WaitForSingleObject(p_internal
->thread_id
, INFINITE
); 
 260   if (wxThread::IsMain()) 
 263   GetExitCodeThread(p_internal
->thread_id
, &exit_code
); 
 264   CloseHandle(p_internal
->thread_id
); 
 266   p_internal
->state 
= STATE_IDLE
; 
 268   return (void *)exit_code
; 
 271 unsigned long wxThread::GetID() 
 273   return (unsigned long)p_internal
->tid
; 
 276 bool wxThread::IsMain() 
 278   return (GetCurrentThread() == p_mainid
); 
 283   p_internal 
= new wxThreadInternal(); 
 285   p_internal
->defer 
= FALSE
; 
 286   p_internal
->prio  
= WXTHREAD_DEFAULT_PRIORITY
; 
 287   p_internal
->state 
= STATE_IDLE
; 
 290 wxThread::~wxThread() 
 297 // The default callback just joins the thread and throws away the result. 
 298 void wxThread::OnExit() 
 303 // Automatic initialization 
 304 class wxThreadModule 
: public wxModule 
{ 
 305   DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 307   virtual bool OnInit(void) { 
 308     p_mainid 
= GetCurrentThread(); 
 314   virtual void OnExit(void) { 
 315     wxMainMutex
.Unlock(); 
 319 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)