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"
40 //--------------------------------------------------------------------
42 //--------------------------------------------------------------------
44 static pthread_t p_mainid
;
46 wxMutex
*wxMainMutex
; /* controls access to all GUI functions */
48 //--------------------------------------------------------------------
49 // common GUI thread code
50 //--------------------------------------------------------------------
52 #include "threadgui.inc"
54 //--------------------------------------------------------------------
55 // wxMutex (Posix implementation)
56 //--------------------------------------------------------------------
61 pthread_mutex_t p_mutex
;
66 p_internal
= new wxMutexInternal
;
67 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
74 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
76 pthread_mutex_destroy(&(p_internal
->p_mutex
));
80 wxMutexError
wxMutex::Lock()
84 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
86 return wxMUTEX_DEAD_LOCK
;
89 return wxMUTEX_NO_ERROR
;
92 wxMutexError
wxMutex::TryLock()
99 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
102 case EBUSY
: return wxMUTEX_BUSY
;
105 return wxMUTEX_NO_ERROR
;
108 wxMutexError
wxMutex::Unlock()
113 return wxMUTEX_UNLOCKED
;
115 pthread_mutex_unlock(&(p_internal
->p_mutex
));
116 return wxMUTEX_NO_ERROR
;
119 //--------------------------------------------------------------------
120 // wxCondition (Posix implementation)
121 //--------------------------------------------------------------------
123 class wxConditionInternal
126 pthread_cond_t p_condition
;
129 wxCondition::wxCondition()
131 p_internal
= new wxConditionInternal
;
132 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
135 wxCondition::~wxCondition()
137 pthread_cond_destroy(&(p_internal
->p_condition
));
141 void wxCondition::Wait(wxMutex
& mutex
)
143 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
146 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
148 struct timespec tspec
;
150 tspec
.tv_sec
= time(NULL
)+sec
;
151 tspec
.tv_nsec
= nsec
;
152 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
155 void wxCondition::Signal()
157 pthread_cond_signal(&(p_internal
->p_condition
));
160 void wxCondition::Broadcast()
162 pthread_cond_broadcast(&(p_internal
->p_condition
));
165 //--------------------------------------------------------------------
166 // wxThread (Posix implementation)
167 //--------------------------------------------------------------------
169 class wxThreadInternal
172 wxThreadInternal() { state
= STATE_IDLE
; }
173 ~wxThreadInternal() {}
174 static void *PthreadStart(void *ptr
);
181 void *wxThreadInternal::PthreadStart(void *ptr
)
183 wxThread
*thread
= (wxThread
*)ptr
;
185 /* Call the main entry */
186 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
187 void* status
= thread
->Entry();
189 thread
->Exit(status
);
194 wxThreadError
wxThread::Create()
197 int min_prio
, max_prio
, p
;
198 struct sched_param sp
;
200 if (p_internal
->state
!= STATE_IDLE
)
201 return wxTHREAD_RUNNING
;
203 /* Change thread priority */
204 pthread_attr_init(&a
);
205 pthread_attr_getschedpolicy(&a
, &p
);
207 min_prio
= sched_get_priority_min(p
);
208 max_prio
= sched_get_priority_max(p
);
210 pthread_attr_getschedparam(&a
, &sp
);
211 sp
.sched_priority
= min_prio
+
212 (p_internal
->prio
*(max_prio
-min_prio
))/100;
213 pthread_attr_setschedparam(&a
, &sp
);
215 // this is the point of no return
216 p_internal
->state
= STATE_RUNNING
;
217 if (pthread_create(&p_internal
->thread_id
, &a
,
218 wxThreadInternal::PthreadStart
, (void *)this) != 0)
220 p_internal
->state
= STATE_IDLE
;
221 pthread_attr_destroy(&a
);
222 return wxTHREAD_NO_RESOURCE
;
224 pthread_attr_destroy(&a
);
226 return wxTHREAD_NO_ERROR
;
229 void wxThread::SetPriority(int prio
)
231 if (p_internal
->state
== STATE_RUNNING
)
234 if (prio
> 100) prio
= 100;
236 if (prio
< 0) prio
= 0;
238 p_internal
->prio
= prio
;
241 int wxThread::GetPriority() const
243 return p_internal
->prio
;
246 void wxThread::DeferDestroy(bool on
)
249 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
251 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
254 wxThreadError
wxThread::Destroy()
258 if (p_internal
->state
== STATE_RUNNING
)
260 res
= pthread_cancel(p_internal
->thread_id
);
262 p_internal
->state
= STATE_CANCELED
;
265 return wxTHREAD_NO_ERROR
;
268 wxThreadError
wxThread::Pause()
270 if (p_internal
->state
!= STATE_RUNNING
)
271 return wxTHREAD_NOT_RUNNING
;
273 if (!p_internal
->defer_destroy
)
274 return wxTHREAD_MISC_ERROR
;
276 p_internal
->state
= STATE_PAUSING
;
277 return wxTHREAD_NO_ERROR
;
280 wxThreadError
wxThread::Resume()
282 if (p_internal
->state
== STATE_PAUSING
|| p_internal
->state
== STATE_PAUSED
)
283 p_internal
->state
= STATE_RUNNING
;
285 return wxTHREAD_NO_ERROR
;
288 void *wxThread::Join()
292 if (p_internal
->state
!= STATE_IDLE
)
294 bool do_unlock
= wxThread::IsMain();
296 while (p_internal
->state
== STATE_RUNNING
)
299 if (do_unlock
) wxMainMutex
->Unlock();
301 pthread_join(p_internal
->thread_id
, &status
);
303 if (do_unlock
) wxMainMutex
->Lock();
305 p_internal
->state
= STATE_IDLE
;
311 unsigned long wxThread::GetID() const
313 return p_internal
->thread_id
;
316 void wxThread::Exit(void *status
)
318 wxThread
* ptr
= this;
320 THREAD_SEND_EXIT_MSG(ptr
);
321 p_internal
->state
= STATE_EXITED
;
322 pthread_exit(status
);
325 bool wxThread::TestDestroy()
327 if (p_internal
->state
== STATE_PAUSING
)
329 p_internal
->state
= STATE_PAUSED
;
330 while (p_internal
->state
== STATE_PAUSED
)
332 pthread_testcancel();
336 pthread_testcancel();
338 return TRUE
; /* what is this for? */
341 bool wxThread::IsMain()
343 return (bool)pthread_equal(pthread_self(), p_mainid
);
346 bool wxThread::IsRunning() const
348 return (p_internal
->state
== STATE_RUNNING
);
351 bool wxThread::IsAlive() const
353 return (p_internal
->state
== STATE_RUNNING
) ||
354 (p_internal
->state
== STATE_PAUSING
) ||
355 (p_internal
->state
== STATE_PAUSED
);
360 p_internal
= new wxThreadInternal();
363 wxThread::~wxThread()
370 /* The default callback just joins the thread and throws away the result. */
371 void wxThread::OnExit()
376 //--------------------------------------------------------------------
378 //--------------------------------------------------------------------
380 class wxThreadModule
: public wxModule
383 virtual bool OnInit();
384 virtual void OnExit();
387 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
390 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
392 bool wxThreadModule::OnInit()
394 wxMainMutex
= new wxMutex();
396 p_mainid
= (int)getpid();
401 void wxThreadModule::OnExit()
403 wxMainMutex
->Unlock();