1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread Implementation for Posix threads
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
5 // Modified by: Robert Roebling
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "thread.h"
20 #include "wx/module.h"
21 #include "wx/thread.h"
30 #include <sys/types.h>
35 //--------------------------------------------------------------------
37 //--------------------------------------------------------------------
49 //--------------------------------------------------------------------
51 //--------------------------------------------------------------------
53 static pthread_t p_mainid
;
55 wxMutex
*wxMainMutex
= (wxMutex
*) NULL
; /* controls access to all GUI functions */
59 static int p_thrd_pipe
[2] = { -1, -1 };
61 //-------------------------------------------------------------------------
63 //-------------------------------------------------------------------------
65 static void wxThreadGuiInit()
70 static void wxThreadGuiExit()
75 void wxMutexGuiEnter()
81 void wxMutexGuiLeave()
84 wxMainMutex
->Unlock();
87 //--------------------------------------------------------------------
88 // wxMutex (Posix implementation)
89 //--------------------------------------------------------------------
94 pthread_mutex_t p_mutex
;
99 p_internal
= new wxMutexInternal
;
100 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
107 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
109 pthread_mutex_destroy(&(p_internal
->p_mutex
));
113 wxMutexError
wxMutex::Lock()
117 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
119 return wxMUTEX_DEAD_LOCK
;
122 return wxMUTEX_NO_ERROR
;
125 wxMutexError
wxMutex::TryLock()
132 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
135 case EBUSY
: return wxMUTEX_BUSY
;
138 return wxMUTEX_NO_ERROR
;
141 wxMutexError
wxMutex::Unlock()
146 return wxMUTEX_UNLOCKED
;
148 pthread_mutex_unlock(&(p_internal
->p_mutex
));
149 return wxMUTEX_NO_ERROR
;
152 //--------------------------------------------------------------------
153 // wxCondition (Posix implementation)
154 //--------------------------------------------------------------------
156 class wxConditionInternal
159 pthread_cond_t p_condition
;
162 wxCondition::wxCondition()
164 p_internal
= new wxConditionInternal
;
165 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
168 wxCondition::~wxCondition()
170 pthread_cond_destroy(&(p_internal
->p_condition
));
174 void wxCondition::Wait(wxMutex
& mutex
)
176 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
179 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
181 struct timespec tspec
;
183 tspec
.tv_sec
= time(NULL
)+sec
;
184 tspec
.tv_nsec
= nsec
;
185 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
188 void wxCondition::Signal()
190 pthread_cond_signal(&(p_internal
->p_condition
));
193 void wxCondition::Broadcast()
195 pthread_cond_broadcast(&(p_internal
->p_condition
));
198 //--------------------------------------------------------------------
199 // wxThread (Posix implementation)
200 //--------------------------------------------------------------------
202 class wxThreadInternal
205 wxThreadInternal() { state
= STATE_IDLE
; }
206 ~wxThreadInternal() {}
207 static void *PthreadStart(void *ptr
);
214 void *wxThreadInternal::PthreadStart(void *ptr
)
216 wxThread
*thread
= (wxThread
*)ptr
;
218 // Call the main entry
219 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
220 void* status
= thread
->Entry();
222 thread
->Exit(status
);
227 wxThreadError
wxThread::Create()
230 int min_prio
, max_prio
, p
;
231 struct sched_param sp
;
233 if (p_internal
->state
!= STATE_IDLE
)
234 return wxTHREAD_RUNNING
;
236 // Change thread priority
237 pthread_attr_init(&a
);
238 pthread_attr_getschedpolicy(&a
, &p
);
240 min_prio
= sched_get_priority_min(p
);
241 max_prio
= sched_get_priority_max(p
);
243 pthread_attr_getschedparam(&a
, &sp
);
244 sp
.sched_priority
= min_prio
+
245 (p_internal
->prio
*(max_prio
-min_prio
))/100;
246 pthread_attr_setschedparam(&a
, &sp
);
248 // this is the point of no return
249 p_internal
->state
= STATE_RUNNING
;
250 if (pthread_create(&p_internal
->thread_id
, &a
,
251 wxThreadInternal::PthreadStart
, (void *)this) != 0)
253 p_internal
->state
= STATE_IDLE
;
254 pthread_attr_destroy(&a
);
255 return wxTHREAD_NO_RESOURCE
;
257 pthread_attr_destroy(&a
);
259 return wxTHREAD_NO_ERROR
;
262 void wxThread::SetPriority(int prio
)
264 if (p_internal
->state
== STATE_RUNNING
)
267 if (prio
> 100) prio
= 100;
269 if (prio
< 0) prio
= 0;
271 p_internal
->prio
= prio
;
274 int wxThread::GetPriority() const
276 return p_internal
->prio
;
279 void wxThread::DeferDestroy(bool on
)
282 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
284 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
287 wxThreadError
wxThread::Destroy()
291 if (p_internal
->state
== STATE_RUNNING
)
293 res
= pthread_cancel(p_internal
->thread_id
);
295 p_internal
->state
= STATE_CANCELED
;
298 return wxTHREAD_NO_ERROR
;
301 wxThreadError
wxThread::Pause()
303 if (p_internal
->state
!= STATE_RUNNING
)
304 return wxTHREAD_NOT_RUNNING
;
306 if (!p_internal
->defer_destroy
)
307 return wxTHREAD_MISC_ERROR
;
309 p_internal
->state
= STATE_PAUSING
;
310 return wxTHREAD_NO_ERROR
;
313 wxThreadError
wxThread::Resume()
315 if (p_internal
->state
== STATE_PAUSING
|| p_internal
->state
== STATE_PAUSED
)
316 p_internal
->state
= STATE_RUNNING
;
318 return wxTHREAD_NO_ERROR
;
321 void *wxThread::Join()
325 if (p_internal
->state
!= STATE_IDLE
)
327 bool do_unlock
= wxThread::IsMain();
329 while (p_internal
->state
== STATE_RUNNING
)
332 if (do_unlock
) wxMainMutex
->Unlock();
334 pthread_join(p_internal
->thread_id
, &status
);
336 if (do_unlock
) wxMainMutex
->Lock();
338 p_internal
->state
= STATE_IDLE
;
344 unsigned long wxThread::GetID() const
346 return p_internal
->thread_id
;
349 void wxThread::Exit(void *status
)
351 wxThread
* ptr
= this;
353 /* THREAD_SEND_EXIT_MSG(ptr); TODO for Xt */
355 p_internal
->state
= STATE_EXITED
;
356 pthread_exit(status
);
359 void wxThread::TestDestroy()
361 if (p_internal
->state
== STATE_PAUSING
)
363 p_internal
->state
= STATE_PAUSED
;
364 while (p_internal
->state
== STATE_PAUSED
)
366 pthread_testcancel();
370 pthread_testcancel();
373 bool wxThread::IsMain()
375 return (bool)pthread_equal(pthread_self(), p_mainid
);
378 bool wxThread::IsRunning() const
380 return (p_internal
->state
== STATE_RUNNING
);
383 bool wxThread::IsAlive() const
385 return (p_internal
->state
== STATE_RUNNING
) ||
386 (p_internal
->state
== STATE_PAUSING
) ||
387 (p_internal
->state
== STATE_PAUSED
);
392 p_internal
= new wxThreadInternal();
395 wxThread::~wxThread()
402 // The default callback just joins the thread and throws away the result.
403 void wxThread::OnExit()
408 //--------------------------------------------------------------------
410 //--------------------------------------------------------------------
412 class wxThreadModule
: public wxModule
414 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
417 virtual bool OnInit()
419 wxMainMutex
= new wxMutex();
421 p_mainid
= pthread_self();
427 virtual void OnExit()
429 wxMainMutex
->Unlock();
435 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)