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"
35 #include <sys/types.h>
40 //--------------------------------------------------------------------
42 //--------------------------------------------------------------------
54 //--------------------------------------------------------------------
56 //--------------------------------------------------------------------
58 static pthread_t p_mainid
;
60 wxMutex
*wxMainMutex
= (wxMutex
*) NULL
; /* controls access to all GUI functions */
64 static int p_thrd_pipe
[2] = { -1, -1 };
66 //-------------------------------------------------------------------------
68 //-------------------------------------------------------------------------
70 static void wxThreadGuiInit()
75 static void wxThreadGuiExit()
80 void wxMutexGuiEnter()
86 void wxMutexGuiLeave()
89 wxMainMutex
->Unlock();
92 //--------------------------------------------------------------------
93 // wxMutex (Posix implementation)
94 //--------------------------------------------------------------------
99 pthread_mutex_t p_mutex
;
104 p_internal
= new wxMutexInternal
;
105 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
112 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
114 pthread_mutex_destroy(&(p_internal
->p_mutex
));
118 wxMutexError
wxMutex::Lock()
122 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
124 return wxMUTEX_DEAD_LOCK
;
127 return wxMUTEX_NO_ERROR
;
130 wxMutexError
wxMutex::TryLock()
137 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
140 case EBUSY
: return wxMUTEX_BUSY
;
143 return wxMUTEX_NO_ERROR
;
146 wxMutexError
wxMutex::Unlock()
151 return wxMUTEX_UNLOCKED
;
153 pthread_mutex_unlock(&(p_internal
->p_mutex
));
154 return wxMUTEX_NO_ERROR
;
157 //--------------------------------------------------------------------
158 // wxCondition (Posix implementation)
159 //--------------------------------------------------------------------
161 class wxConditionInternal
164 pthread_cond_t p_condition
;
167 wxCondition::wxCondition()
169 p_internal
= new wxConditionInternal
;
170 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
173 wxCondition::~wxCondition()
175 pthread_cond_destroy(&(p_internal
->p_condition
));
179 void wxCondition::Wait(wxMutex
& mutex
)
181 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
184 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
186 struct timespec tspec
;
188 tspec
.tv_sec
= time(NULL
)+sec
;
189 tspec
.tv_nsec
= nsec
;
190 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
193 void wxCondition::Signal()
195 pthread_cond_signal(&(p_internal
->p_condition
));
198 void wxCondition::Broadcast()
200 pthread_cond_broadcast(&(p_internal
->p_condition
));
203 //--------------------------------------------------------------------
204 // wxThread (Posix implementation)
205 //--------------------------------------------------------------------
207 class wxThreadInternal
210 wxThreadInternal() { state
= STATE_IDLE
; }
211 ~wxThreadInternal() {}
212 static void *PthreadStart(void *ptr
);
219 void *wxThreadInternal::PthreadStart(void *ptr
)
221 wxThread
*thread
= (wxThread
*)ptr
;
223 // Call the main entry
224 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
225 void* status
= thread
->Entry();
227 thread
->Exit(status
);
232 wxThreadError
wxThread::Create()
235 int min_prio
, max_prio
, p
;
236 struct sched_param sp
;
238 if (p_internal
->state
!= STATE_IDLE
)
239 return wxTHREAD_RUNNING
;
241 // Change thread priority
242 pthread_attr_init(&a
);
243 pthread_attr_getschedpolicy(&a
, &p
);
245 min_prio
= sched_get_priority_min(p
);
246 max_prio
= sched_get_priority_max(p
);
248 pthread_attr_getschedparam(&a
, &sp
);
249 sp
.sched_priority
= min_prio
+
250 (p_internal
->prio
*(max_prio
-min_prio
))/100;
251 pthread_attr_setschedparam(&a
, &sp
);
253 // this is the point of no return
254 p_internal
->state
= STATE_RUNNING
;
255 if (pthread_create(&p_internal
->thread_id
, &a
,
256 wxThreadInternal::PthreadStart
, (void *)this) != 0)
258 p_internal
->state
= STATE_IDLE
;
259 pthread_attr_destroy(&a
);
260 return wxTHREAD_NO_RESOURCE
;
262 pthread_attr_destroy(&a
);
264 return wxTHREAD_NO_ERROR
;
267 void wxThread::SetPriority(int prio
)
269 if (p_internal
->state
== STATE_RUNNING
)
272 if (prio
> 100) prio
= 100;
274 if (prio
< 0) prio
= 0;
276 p_internal
->prio
= prio
;
279 int wxThread::GetPriority() const
281 return p_internal
->prio
;
284 void wxThread::DeferDestroy(bool on
)
287 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
289 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
292 wxThreadError
wxThread::Destroy()
296 if (p_internal
->state
== STATE_RUNNING
)
298 res
= pthread_cancel(p_internal
->thread_id
);
300 p_internal
->state
= STATE_CANCELED
;
303 return wxTHREAD_NO_ERROR
;
306 wxThreadError
wxThread::Pause()
308 if (p_internal
->state
!= STATE_RUNNING
)
309 return wxTHREAD_NOT_RUNNING
;
311 if (!p_internal
->defer_destroy
)
312 return wxTHREAD_MISC_ERROR
;
314 p_internal
->state
= STATE_PAUSING
;
315 return wxTHREAD_NO_ERROR
;
318 wxThreadError
wxThread::Resume()
320 if (p_internal
->state
== STATE_PAUSING
|| p_internal
->state
== STATE_PAUSED
)
321 p_internal
->state
= STATE_RUNNING
;
323 return wxTHREAD_NO_ERROR
;
326 void *wxThread::Join()
330 if (p_internal
->state
!= STATE_IDLE
)
332 bool do_unlock
= wxThread::IsMain();
334 while (p_internal
->state
== STATE_RUNNING
)
337 if (do_unlock
) wxMainMutex
->Unlock();
339 pthread_join(p_internal
->thread_id
, &status
);
341 if (do_unlock
) wxMainMutex
->Lock();
343 p_internal
->state
= STATE_IDLE
;
349 unsigned long wxThread::GetID() const
351 return p_internal
->thread_id
;
354 void wxThread::Exit(void *status
)
356 wxThread
* ptr
= this;
358 /* THREAD_SEND_EXIT_MSG(ptr); TODO for Xt */
360 p_internal
->state
= STATE_EXITED
;
361 pthread_exit(status
);
364 void wxThread::TestDestroy()
366 if (p_internal
->state
== STATE_PAUSING
)
368 p_internal
->state
= STATE_PAUSED
;
369 while (p_internal
->state
== STATE_PAUSED
)
371 pthread_testcancel();
375 pthread_testcancel();
378 bool wxThread::IsMain()
380 return (bool)pthread_equal(pthread_self(), p_mainid
);
383 bool wxThread::IsRunning() const
385 return (p_internal
->state
== STATE_RUNNING
);
388 bool wxThread::IsAlive() const
390 return (p_internal
->state
== STATE_RUNNING
) ||
391 (p_internal
->state
== STATE_PAUSING
) ||
392 (p_internal
->state
== STATE_PAUSED
);
397 p_internal
= new wxThreadInternal();
400 wxThread::~wxThread()
407 // The default callback just joins the thread and throws away the result.
408 void wxThread::OnExit()
413 //--------------------------------------------------------------------
415 //--------------------------------------------------------------------
417 class wxThreadModule
: public wxModule
420 virtual bool OnInit();
421 virtual void OnExit();
424 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
427 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
429 bool wxThreadModule::OnInit()
431 wxMainMutex
= new wxMutex();
433 p_mainid
= pthread_self();
439 void wxThreadModule::OnExit()
441 wxMainMutex
->Unlock();