1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxThread (Posix) Implementation 
   4 // Author:      Original from Wolfram Gloger/Guilhem Lavaux 
   8 // Copyright:   (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998) 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "thread.h" 
  19 #include "wx/thread.h" 
  20 #include "wx/module.h" 
  33 ///////////////////////////////////////////////////////////////////////////// 
  35 ///////////////////////////////////////////////////////////////////////////// 
  37 static pthread_t p_mainid
; 
  38 static wxMutex p_list_mutex
; 
  39 static wxList p_threads_list
; 
  41 wxMutex 
*wxMainMutex
; // controls access to all GUI functions 
  43 ///////////////////////////////////////////////////////////////////////////// 
  45 ///////////////////////////////////////////////////////////////////////////// 
  46 #include "threadgui.inc" 
  48 ///////////////////////////////////////////////////////////////////////////// 
  49 // wxThread: Posix Thread implementation (Mutex) 
  50 ///////////////////////////////////////////////////////////////////////////// 
  52 class wxMutexInternal 
{ 
  54   pthread_mutex_t p_mutex
; 
  59   p_internal 
= new wxMutexInternal
; 
  60   pthread_mutex_init(&(p_internal
->p_mutex
), NULL
); 
  67     wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked 
); 
  69   pthread_mutex_destroy(&(p_internal
->p_mutex
)); 
  73 wxMutexError 
wxMutex::Lock() 
  77   err 
= pthread_mutex_lock(&(p_internal
->p_mutex
)); 
  79     return MUTEX_DEAD_LOCK
; 
  81   return MUTEX_NO_ERROR
; 
  84 wxMutexError 
wxMutex::TryLock() 
  90   err 
= pthread_mutex_trylock(&(p_internal
->p_mutex
)); 
  92   case EBUSY
: return MUTEX_BUSY
; 
  95   return MUTEX_NO_ERROR
; 
  98 wxMutexError 
wxMutex::Unlock() 
 103     return MUTEX_UNLOCKED
; 
 104   pthread_mutex_unlock(&(p_internal
->p_mutex
)); 
 105   return MUTEX_NO_ERROR
; 
 108 ///////////////////////////////////////////////////////////////////////////// 
 109 // wxThread: Posix Thread implementation (Condition) 
 110 ///////////////////////////////////////////////////////////////////////////// 
 112 class wxConditionInternal 
{ 
 114   pthread_cond_t p_condition
; 
 117 wxCondition::wxCondition() 
 119   p_internal 
= new wxConditionInternal
; 
 120   pthread_cond_init(&(p_internal
->p_condition
), NULL
); 
 123 wxCondition::~wxCondition() 
 125   pthread_cond_destroy(&(p_internal
->p_condition
)); 
 129 void wxCondition::Wait(wxMutex
& mutex
) 
 131   pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
)); 
 134 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
) 
 136   struct timespec tspec
; 
 138   tspec
.tv_sec 
= time(NULL
)+sec
; 
 139   tspec
.tv_nsec 
= nsec
; 
 140   return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
); 
 143 void wxCondition::Signal() 
 145   pthread_cond_signal(&(p_internal
->p_condition
)); 
 148 void wxCondition::Broadcast() 
 150   pthread_cond_broadcast(&(p_internal
->p_condition
)); 
 153 ///////////////////////////////////////////////////////////////////////////// 
 154 // wxThread: Posix Thread implementation (Thread) 
 155 ///////////////////////////////////////////////////////////////////////////// 
 157 class wxThreadInternal 
{ 
 159   wxThreadInternal() { state 
= STATE_IDLE
; } 
 160   ~wxThreadInternal() {} 
 161   static void *PthreadStart(void *ptr
); 
 169 void *wxThreadInternal::PthreadStart(void *ptr
) 
 171   wxThread 
*thread 
= (wxThread 
*)ptr
; 
 173   // Add the current thread to the list 
 175   thread
->p_internal
->id 
= p_threads_list
.Number(); 
 176   p_threads_list
.Append((wxObject 
*)thread
); 
 177   p_list_mutex
.Unlock(); 
 179   // Call the main entry 
 180   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
); 
 181   void* status 
= thread
->Entry(); 
 183   thread
->Exit(status
); 
 188 wxThreadError 
wxThread::Create() 
 191   int min_prio
, max_prio
, p
; 
 192   struct sched_param sp
; 
 194   if (p_internal
->state 
!= STATE_IDLE
) 
 195     return THREAD_RUNNING
; 
 197   // Change thread priority 
 198   pthread_attr_init(&a
); 
 199   pthread_attr_getschedpolicy(&a
, &p
); 
 201   min_prio 
= sched_get_priority_min(p
); 
 202   max_prio 
= sched_get_priority_max(p
); 
 204   pthread_attr_getschedparam(&a
, &sp
); 
 205   sp
.sched_priority 
= min_prio 
+ 
 206                (p_internal
->prio
*(max_prio
-min_prio
))/100; 
 207   pthread_attr_setschedparam(&a
, &sp
); 
 209   // this is the point of no return 
 210   p_internal
->state 
= STATE_RUNNING
; 
 211   if (pthread_create(&p_internal
->thread_id
, &a
, 
 212                      wxThreadInternal::PthreadStart
, (void *)this) != 0) { 
 213     p_internal
->state 
= STATE_IDLE
; 
 214     pthread_attr_destroy(&a
); 
 215     return THREAD_NO_RESOURCE
; 
 217   pthread_attr_destroy(&a
); 
 219   return THREAD_NO_ERROR
; 
 222 void wxThread::SetPriority(int prio
) 
 224   if (p_internal
->state 
== STATE_RUNNING
) 
 231   p_internal
->prio 
= prio
; 
 234 int wxThread::GetPriority() const 
 236   return p_internal
->prio
; 
 239 void wxThread::DeferDestroy(bool on
) 
 242     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
); 
 244     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
); 
 247 wxThreadError 
wxThread::Destroy() 
 251   if (p_internal
->state 
== STATE_RUNNING
) { 
 252     res 
= pthread_cancel(p_internal
->thread_id
); 
 254       p_internal
->state 
= STATE_CANCELED
; 
 257   return THREAD_NO_ERROR
; 
 260 wxThreadError 
wxThread::Pause() 
 262   if (p_internal
->state 
!= STATE_RUNNING
) 
 263     return THREAD_NOT_RUNNING
; 
 265   if (!p_internal
->defer_destroy
) 
 266     return THREAD_MISC_ERROR
; 
 268   p_internal
->state 
= STATE_PAUSING
; 
 269   return THREAD_NO_ERROR
; 
 272 wxThreadError 
wxThread::Resume() 
 274   if (p_internal
->state 
== STATE_PAUSING 
|| p_internal
->state 
== STATE_PAUSED
) 
 275     p_internal
->state 
= STATE_RUNNING
; 
 277   return THREAD_NO_ERROR
; 
 280 void *wxThread::Join() 
 284   if (p_internal
->state 
!= STATE_IDLE
) { 
 285     bool do_unlock 
= wxThread::IsMain(); 
 287     while (p_internal
->state 
== STATE_RUNNING
) 
 291       wxMainMutex
->Unlock(); 
 292     pthread_join(p_internal
->thread_id
, &status
); 
 297     delete p_threads_list
.Nth(p_internal
->id
); 
 298     p_list_mutex
.Unlock(); 
 300     p_internal
->state 
= STATE_IDLE
; 
 305 unsigned long wxThread::GetID() const 
 307   return p_internal
->id
; 
 310 wxThread 
*wxThread::GetThreadFromID(unsigned long id
) 
 312   wxNode 
*node 
= p_threads_list
.Nth(id
); 
 316   return (wxThread 
*)node
->Data(); 
 319 void wxThread::Exit(void *status
) 
 321   wxThread
* ptr 
= this; 
 323   THREAD_SEND_EXIT_MSG(ptr
); 
 324   p_internal
->state 
= STATE_EXITED
; 
 325   pthread_exit(status
); 
 328 void wxThread::TestDestroy() 
 330   if (p_internal
->state 
== STATE_PAUSING
) { 
 331     p_internal
->state 
= STATE_PAUSED
; 
 332     while (p_internal
->state 
== STATE_PAUSED
) { 
 333       pthread_testcancel(); 
 337   pthread_testcancel(); 
 340 bool wxThread::IsMain() 
 342   return (bool)pthread_equal(pthread_self(), p_mainid
); 
 345 bool wxThread::IsRunning() const 
 347   return (p_internal
->state 
== STATE_RUNNING
); 
 350 bool wxThread::IsAlive() const 
 352   return (p_internal
->state 
== STATE_RUNNING
) || 
 353          (p_internal
->state 
== STATE_PAUSING
) || 
 354          (p_internal
->state 
== STATE_PAUSED
); 
 359   p_internal 
= new wxThreadInternal(); 
 362 wxThread::~wxThread() 
 369 // The default callback just joins the thread and throws away the result. 
 370 void wxThread::OnExit() 
 375 // Automatic initialization 
 376 class wxThreadModule 
: public wxModule 
{ 
 377   DECLARE_DYNAMIC_CLASS(wxThreadModule
) 
 379   virtual bool OnInit() { 
 380     wxMainMutex 
= new wxMutex(); 
 382     p_mainid 
= pthread_self(); 
 383 //    p_threads_list = wxList(wxKEY_INTEGER); 
 389   virtual void OnExit() { 
 390     wxMainMutex
->Unlock(); 
 396 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)