1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread (Posix) Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "thread.h"
20 #include "wx/thread.h"
21 #include "wx/module.h"
31 /////////////////////////////////////////////////////////////////////////////
33 /////////////////////////////////////////////////////////////////////////////
35 static pthread_t p_mainid
;
36 wxMutex wxMainMutex
; // controls access to all GUI functions
38 /////////////////////////////////////////////////////////////////////////////
40 /////////////////////////////////////////////////////////////////////////////
41 #include "threadgui.inc"
43 /////////////////////////////////////////////////////////////////////////////
44 // wxThread: Posix Thread implementation (Mutex)
45 /////////////////////////////////////////////////////////////////////////////
47 class wxMutexInternal
{
49 pthread_mutex_t p_mutex
;
54 p_internal
= new wxMutexInternal
;
55 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
62 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n",
65 pthread_mutex_destroy(&(p_internal
->p_mutex
));
69 wxMutexError
wxMutex::Lock()
73 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
75 return MUTEX_DEAD_LOCK
;
77 return MUTEX_NO_ERROR
;
80 wxMutexError
wxMutex::TryLock()
86 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
88 case EBUSY
: return MUTEX_BUSY
;
91 return MUTEX_NO_ERROR
;
94 wxMutexError
wxMutex::Unlock()
99 return MUTEX_UNLOCKED
;
100 pthread_mutex_unlock(&(p_internal
->p_mutex
));
101 return MUTEX_NO_ERROR
;
104 /////////////////////////////////////////////////////////////////////////////
105 // wxThread: Posix Thread implementation (Condition)
106 /////////////////////////////////////////////////////////////////////////////
108 class wxConditionInternal
{
110 pthread_cond_t p_condition
;
113 wxCondition::wxCondition()
115 p_internal
= new wxConditionInternal
;
116 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
119 wxCondition::~wxCondition()
121 pthread_cond_destroy(&(p_internal
->p_condition
));
125 void wxCondition::Wait(wxMutex
& mutex
)
127 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
130 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
132 struct timespec tspec
;
134 tspec
.tv_sec
= time(NULL
)+sec
;
135 tspec
.tv_nsec
= nsec
;
136 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
139 void wxCondition::Signal()
141 pthread_cond_signal(&(p_internal
->p_condition
));
144 void wxCondition::Broadcast()
146 pthread_cond_broadcast(&(p_internal
->p_condition
));
149 /////////////////////////////////////////////////////////////////////////////
150 // wxThread: Posix Thread implementation (Thread)
151 /////////////////////////////////////////////////////////////////////////////
153 class wxThreadInternal
{
155 wxThreadInternal() { state
= STATE_IDLE
; }
156 ~wxThreadInternal() {}
157 static void *PthreadStart(void *ptr
);
163 void *wxThreadInternal::PthreadStart(void *ptr
)
165 wxThread
*thread
= (wxThread
*)ptr
;
167 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
168 void* status
= thread
->Entry();
169 thread
->Exit(status
);
174 wxThreadError
wxThread::Create()
177 int min_prio
, max_prio
, p
;
178 struct sched_param sp
;
180 if (p_internal
->state
!= STATE_IDLE
)
181 return THREAD_RUNNING
;
183 // Change thread priority
184 pthread_attr_init(&a
);
185 pthread_attr_getschedpolicy(&a
, &p
);
187 min_prio
= sched_get_priority_min(p
);
188 max_prio
= sched_get_priority_max(p
);
190 pthread_attr_getschedparam(&a
, &sp
);
191 sp
.sched_priority
= min_prio
+
192 (p_internal
->prio
*(max_prio
-min_prio
))/100;
193 pthread_attr_setschedparam(&a
, &sp
);
195 // this is the point of no return
196 p_internal
->state
= STATE_RUNNING
;
197 if (pthread_create(&p_internal
->thread_id
, &a
,
198 wxThreadInternal::PthreadStart
, (void *)this) != 0) {
199 p_internal
->state
= STATE_IDLE
;
200 pthread_attr_destroy(&a
);
201 return THREAD_NO_RESOURCE
;
203 pthread_attr_destroy(&a
);
204 return THREAD_NO_ERROR
;
207 void wxThread::SetPriority(int prio
)
209 if (p_internal
->state
== STATE_RUNNING
)
216 p_internal
->prio
= prio
;
219 int wxThread::GetPriority() const
221 return p_internal
->prio
;
224 void wxThread::DeferDestroy(bool on
)
227 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
229 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
232 wxThreadError
wxThread::Destroy()
236 if (p_internal
->state
== STATE_RUNNING
) {
237 res
= pthread_cancel(p_internal
->thread_id
);
239 p_internal
->state
= STATE_CANCELED
;
241 return THREAD_NO_ERROR
;
244 void *wxThread::Join()
248 if (p_internal
->state
!= STATE_IDLE
) {
249 bool do_unlock
= wxThread::IsMain();
251 while (p_internal
->state
== STATE_RUNNING
)
255 wxMainMutex
.Unlock();
256 pthread_join(p_internal
->thread_id
, &status
);
259 p_internal
->state
= STATE_IDLE
;
264 unsigned long wxThread::GetID() const
266 return (unsigned long)p_internal
->thread_id
;
269 void wxThread::Exit(void *status
)
271 wxThread
* ptr
= this;
273 THREAD_SEND_EXIT_MSG(ptr
);
274 p_internal
->state
= STATE_EXITED
;
275 pthread_exit(status
);
278 void wxThread::TestDestroy()
280 pthread_testcancel();
283 bool wxThread::IsMain()
285 return (bool)pthread_equal(pthread_self(), p_mainid
);
290 p_internal
= new wxThreadInternal();
293 wxThread::~wxThread()
300 // The default callback just joins the thread and throws away the result.
301 void wxThread::OnExit()
305 // Automatic initialization
306 class wxThreadModule
: public wxModule
{
307 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
309 virtual bool OnInit() {
311 p_mainid
= pthread_self();
317 virtual void OnExit() {
318 wxMainMutex
.Unlock();
323 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)