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
), (const pthread_mutexattr_t
*) 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()
82 int err
= pthread_mutex_lock( &(p_internal
->p_mutex
) );
85 return wxMUTEX_DEAD_LOCK
;
90 return wxMUTEX_NO_ERROR
;
93 wxMutexError
wxMutex::TryLock()
100 int err
= pthread_mutex_trylock( &(p_internal
->p_mutex
) );
103 case EBUSY
: return wxMUTEX_BUSY
;
108 return wxMUTEX_NO_ERROR
;
111 wxMutexError
wxMutex::Unlock()
119 return wxMUTEX_UNLOCKED
;
122 pthread_mutex_unlock( &(p_internal
->p_mutex
) );
124 return wxMUTEX_NO_ERROR
;
127 //--------------------------------------------------------------------
128 // wxCondition (Posix implementation)
129 //--------------------------------------------------------------------
131 class wxConditionInternal
134 pthread_cond_t p_condition
;
137 wxCondition::wxCondition()
139 p_internal
= new wxConditionInternal
;
140 pthread_cond_init( &(p_internal
->p_condition
), (const pthread_condattr_t
*) NULL
);
143 wxCondition::~wxCondition()
145 pthread_cond_destroy( &(p_internal
->p_condition
) );
150 void wxCondition::Wait(wxMutex
& mutex
)
152 pthread_cond_wait( &(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
) );
155 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
157 struct timespec tspec
;
159 tspec
.tv_sec
= time(0L)+sec
;
160 tspec
.tv_nsec
= nsec
;
161 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
164 void wxCondition::Signal()
166 pthread_cond_signal( &(p_internal
->p_condition
) );
169 void wxCondition::Broadcast()
171 pthread_cond_broadcast( &(p_internal
->p_condition
) );
174 //--------------------------------------------------------------------
175 // wxThread (Posix implementation)
176 //--------------------------------------------------------------------
178 class wxThreadInternal
181 wxThreadInternal() { state
= STATE_IDLE
; }
182 ~wxThreadInternal() {}
183 static void *PthreadStart(void *ptr
);
190 void *wxThreadInternal::PthreadStart(void *ptr
)
192 wxThread
*thread
= (wxThread
*)ptr
;
194 /* Call the main entry */
195 pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS
, (int*) NULL
);
196 void* status
= thread
->Entry();
198 thread
->Exit(status
);
203 wxThreadError
wxThread::Create()
206 int min_prio
, max_prio
, p
;
207 struct sched_param sp
;
209 if (p_internal
->state
!= STATE_IDLE
)
210 return wxTHREAD_RUNNING
;
212 /* Change thread priority */
213 pthread_attr_init(&a
);
214 pthread_attr_getschedpolicy(&a
, &p
);
216 min_prio
= sched_get_priority_min(p
);
217 max_prio
= sched_get_priority_max(p
);
219 pthread_attr_getschedparam(&a
, &sp
);
220 sp
.sched_priority
= min_prio
+
221 (p_internal
->prio
*(max_prio
-min_prio
))/100;
222 pthread_attr_setschedparam(&a
, &sp
);
224 // this is the point of no return
225 p_internal
->state
= STATE_RUNNING
;
226 if (pthread_create(&p_internal
->thread_id
, &a
,
227 wxThreadInternal::PthreadStart
, (void *)this) != 0)
229 p_internal
->state
= STATE_IDLE
;
230 pthread_attr_destroy(&a
);
231 return wxTHREAD_NO_RESOURCE
;
233 pthread_attr_destroy(&a
);
235 return wxTHREAD_NO_ERROR
;
238 void wxThread::SetPriority(int prio
)
240 if (p_internal
->state
== STATE_RUNNING
)
243 if (prio
> 100) prio
= 100;
245 if (prio
< 0) prio
= 0;
247 p_internal
->prio
= prio
;
250 int wxThread::GetPriority() const
252 return p_internal
->prio
;
255 void wxThread::DeferDestroy(bool on
)
258 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, (int*) NULL
);
260 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, (int*) NULL
);
263 wxThreadError
wxThread::Destroy()
267 if (p_internal
->state
== STATE_RUNNING
)
269 res
= pthread_cancel(p_internal
->thread_id
);
271 p_internal
->state
= STATE_CANCELED
;
274 return wxTHREAD_NO_ERROR
;
277 wxThreadError
wxThread::Pause()
279 if (p_internal
->state
!= STATE_RUNNING
)
280 return wxTHREAD_NOT_RUNNING
;
282 if (!p_internal
->defer_destroy
)
283 return wxTHREAD_MISC_ERROR
;
285 p_internal
->state
= STATE_PAUSING
;
286 return wxTHREAD_NO_ERROR
;
289 wxThreadError
wxThread::Resume()
291 if (p_internal
->state
== STATE_PAUSING
|| p_internal
->state
== STATE_PAUSED
)
292 p_internal
->state
= STATE_RUNNING
;
294 return wxTHREAD_NO_ERROR
;
297 void *wxThread::Join()
301 if (p_internal
->state
!= STATE_IDLE
)
303 bool do_unlock
= wxThread::IsMain();
305 while (p_internal
->state
== STATE_RUNNING
)
308 if (do_unlock
) wxMainMutex
->Unlock();
310 pthread_join(p_internal
->thread_id
, &status
);
312 if (do_unlock
) wxMainMutex
->Lock();
314 p_internal
->state
= STATE_IDLE
;
320 unsigned long wxThread::GetID() const
322 return p_internal
->thread_id
;
325 void wxThread::Exit(void *status
)
327 wxThread
* ptr
= this;
329 THREAD_SEND_EXIT_MSG(ptr
);
330 p_internal
->state
= STATE_EXITED
;
331 pthread_exit(status
);
334 bool wxThread::TestDestroy()
336 if (p_internal
->state
== STATE_PAUSING
)
338 p_internal
->state
= STATE_PAUSED
;
339 while (p_internal
->state
== STATE_PAUSED
)
341 pthread_testcancel();
345 pthread_testcancel();
347 return TRUE
; /* what is this for? */
350 bool wxThread::IsMain()
352 return (bool)pthread_equal(pthread_self(), p_mainid
);
355 bool wxThread::IsRunning() const
357 return (p_internal
->state
== STATE_RUNNING
);
360 bool wxThread::IsAlive() const
362 return (p_internal
->state
== STATE_RUNNING
) ||
363 (p_internal
->state
== STATE_PAUSING
) ||
364 (p_internal
->state
== STATE_PAUSED
);
369 p_internal
= new wxThreadInternal();
372 wxThread::~wxThread()
379 /* The default callback just joins the thread and throws away the result. */
380 void wxThread::OnExit()
385 //--------------------------------------------------------------------
387 //--------------------------------------------------------------------
389 class wxThreadModule
: public wxModule
392 virtual bool OnInit();
393 virtual void OnExit();
396 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
399 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)
401 bool wxThreadModule::OnInit()
403 wxMainMutex
= new wxMutex();
405 p_mainid
= (int)getpid();
410 void wxThreadModule::OnExit()
412 wxMainMutex
->Unlock();