1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread (Posix) Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
8 // Copyright: (c) Wolfram Gloger (1996, 1997)
9 // Guilhem Lavaux (1998)
10 // Robert Roebling (1999)
11 // Licence: wxWindows licence
12 /////////////////////////////////////////////////////////////////////////////
15 #pragma implementation "thread.h"
22 #include "wx/thread.h"
23 #include "wx/module.h"
37 //--------------------------------------------------------------------
39 //--------------------------------------------------------------------
41 static pthread_t p_mainid
;
43 wxMutex
*wxMainMutex
; // controls access to all GUI functions
45 //--------------------------------------------------------------------
46 // common GUI thread code
47 //--------------------------------------------------------------------
49 #include "threadgui.inc"
51 //--------------------------------------------------------------------
52 // wxMutex (Posix implementation)
53 //--------------------------------------------------------------------
58 pthread_mutex_t p_mutex
;
63 p_internal
= new wxMutexInternal
;
64 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
71 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
73 pthread_mutex_destroy(&(p_internal
->p_mutex
));
77 wxMutexError
wxMutex::Lock()
81 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
83 return wxMUTEX_DEAD_LOCK
;
86 return wxMUTEX_NO_ERROR
;
89 wxMutexError
wxMutex::TryLock()
96 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
99 case EBUSY
: return wxMUTEX_BUSY
;
102 return wxMUTEX_NO_ERROR
;
105 wxMutexError
wxMutex::Unlock()
110 return wxMUTEX_UNLOCKED
;
112 pthread_mutex_unlock(&(p_internal
->p_mutex
));
113 return wxMUTEX_NO_ERROR
;
116 //--------------------------------------------------------------------
117 // wxCondition (Posix implementation)
118 //--------------------------------------------------------------------
120 class wxConditionInternal
123 pthread_cond_t p_condition
;
126 wxCondition::wxCondition()
128 p_internal
= new wxConditionInternal
;
129 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
132 wxCondition::~wxCondition()
134 pthread_cond_destroy(&(p_internal
->p_condition
));
138 void wxCondition::Wait(wxMutex
& mutex
)
140 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
143 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
145 struct timespec tspec
;
147 tspec
.tv_sec
= time(NULL
)+sec
;
148 tspec
.tv_nsec
= nsec
;
149 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
152 void wxCondition::Signal()
154 pthread_cond_signal(&(p_internal
->p_condition
));
157 void wxCondition::Broadcast()
159 pthread_cond_broadcast(&(p_internal
->p_condition
));
162 //--------------------------------------------------------------------
163 // wxThread (Posix implementation)
164 //--------------------------------------------------------------------
166 class wxThreadInternal
169 wxThreadInternal() { state
= STATE_IDLE
; }
170 ~wxThreadInternal() {}
171 static void *PthreadStart(void *ptr
);
178 void *wxThreadInternal::PthreadStart(void *ptr
)
180 wxThread
*thread
= (wxThread
*)ptr
;
182 // Call the main entry
183 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
184 void* status
= thread
->Entry();
186 thread
->Exit(status
);
191 wxThreadError
wxThread::Create()
194 int min_prio
, max_prio
, p
;
195 struct sched_param sp
;
197 if (p_internal
->state
!= STATE_IDLE
)
198 return wxTHREAD_RUNNING
;
200 // Change thread priority
201 pthread_attr_init(&a
);
202 pthread_attr_getschedpolicy(&a
, &p
);
204 min_prio
= sched_get_priority_min(p
);
205 max_prio
= sched_get_priority_max(p
);
207 pthread_attr_getschedparam(&a
, &sp
);
208 sp
.sched_priority
= min_prio
+
209 (p_internal
->prio
*(max_prio
-min_prio
))/100;
210 pthread_attr_setschedparam(&a
, &sp
);
212 // this is the point of no return
213 p_internal
->state
= STATE_RUNNING
;
214 if (pthread_create(&p_internal
->thread_id
, &a
,
215 wxThreadInternal::PthreadStart
, (void *)this) != 0)
217 p_internal
->state
= STATE_IDLE
;
218 pthread_attr_destroy(&a
);
219 return wxTHREAD_NO_RESOURCE
;
221 pthread_attr_destroy(&a
);
223 return wxTHREAD_NO_ERROR
;
226 void wxThread::SetPriority(int prio
)
228 if (p_internal
->state
== STATE_RUNNING
)
231 if (prio
> 100) prio
= 100;
233 if (prio
< 0) prio
= 0;
235 p_internal
->prio
= prio
;
238 int wxThread::GetPriority() const
240 return p_internal
->prio
;
243 void wxThread::DeferDestroy(bool on
)
246 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
248 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
251 wxThreadError
wxThread::Destroy()
255 if (p_internal
->state
== STATE_RUNNING
)
257 res
= pthread_cancel(p_internal
->thread_id
);
259 p_internal
->state
= STATE_CANCELED
;
262 return wxTHREAD_NO_ERROR
;
265 wxThreadError
wxThread::Pause()
267 if (p_internal
->state
!= STATE_RUNNING
)
268 return wxTHREAD_NOT_RUNNING
;
270 if (!p_internal
->defer_destroy
)
271 return wxTHREAD_MISC_ERROR
;
273 p_internal
->state
= STATE_PAUSING
;
274 return wxTHREAD_NO_ERROR
;
277 wxThreadError
wxThread::Resume()
279 if (p_internal
->state
== STATE_PAUSING
|| p_internal
->state
== STATE_PAUSED
)
280 p_internal
->state
= STATE_RUNNING
;
282 return wxTHREAD_NO_ERROR
;
285 void *wxThread::Join()
289 if (p_internal
->state
!= STATE_IDLE
)
291 bool do_unlock
= wxThread::IsMain();
293 while (p_internal
->state
== STATE_RUNNING
)
296 if (do_unlock
) wxMainMutex
->Unlock();
298 pthread_join(p_internal
->thread_id
, &status
);
300 if (do_unlock
) wxMainMutex
->Lock();
302 p_internal
->state
= STATE_IDLE
;
308 unsigned long wxThread::GetID() const
310 return p_internal
->thread_id
;
313 void wxThread::Exit(void *status
)
315 wxThread
* ptr
= this;
317 THREAD_SEND_EXIT_MSG(ptr
);
318 p_internal
->state
= STATE_EXITED
;
319 pthread_exit(status
);
322 void wxThread::TestDestroy()
324 if (p_internal
->state
== STATE_PAUSING
)
326 p_internal
->state
= STATE_PAUSED
;
327 while (p_internal
->state
== STATE_PAUSED
)
329 pthread_testcancel();
333 pthread_testcancel();
336 bool wxThread::IsMain()
338 return (bool)pthread_equal(pthread_self(), p_mainid
);
341 bool wxThread::IsRunning() const
343 return (p_internal
->state
== STATE_RUNNING
);
346 bool wxThread::IsAlive() const
348 return (p_internal
->state
== STATE_RUNNING
) ||
349 (p_internal
->state
== STATE_PAUSING
) ||
350 (p_internal
->state
== STATE_PAUSED
);
355 p_internal
= new wxThreadInternal();
358 wxThread::~wxThread()
365 // The default callback just joins the thread and throws away the result.
366 void wxThread::OnExit()
371 //--------------------------------------------------------------------
373 //--------------------------------------------------------------------
375 class wxThreadModule
: public wxModule
377 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
380 virtual bool OnInit()
382 wxMainMutex
= new wxMutex();
384 p_mainid
= pthread_self();
390 virtual void OnExit()
392 wxMainMutex
->Unlock();
398 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)