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"
19 #include "wx/thread.h"
20 #include "wx/module.h"
30 /////////////////////////////////////////////////////////////////////////////
32 /////////////////////////////////////////////////////////////////////////////
34 static pthread_t p_mainid
;
35 wxMutex wxMainMutex
; // controls access to all GUI functions
37 /////////////////////////////////////////////////////////////////////////////
39 /////////////////////////////////////////////////////////////////////////////
40 #include "threadgui.inc"
42 /////////////////////////////////////////////////////////////////////////////
43 // wxThread: Posix Thread implementation (Mutex)
44 /////////////////////////////////////////////////////////////////////////////
46 class wxMutexInternal
{
48 pthread_mutex_t p_mutex
;
53 p_internal
= new wxMutexInternal
;
54 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
61 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n",
64 pthread_mutex_destroy(&(p_internal
->p_mutex
));
68 wxMutexError
wxMutex::Lock()
72 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
74 return MUTEX_DEAD_LOCK
;
76 return MUTEX_NO_ERROR
;
79 wxMutexError
wxMutex::TryLock()
85 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
87 case EBUSY
: return MUTEX_BUSY
;
90 return MUTEX_NO_ERROR
;
93 wxMutexError
wxMutex::Unlock()
98 return MUTEX_UNLOCKED
;
99 pthread_mutex_unlock(&(p_internal
->p_mutex
));
100 return MUTEX_NO_ERROR
;
103 /////////////////////////////////////////////////////////////////////////////
104 // wxThread: Posix Thread implementation (Condition)
105 /////////////////////////////////////////////////////////////////////////////
107 class wxConditionInternal
{
109 pthread_cond_t p_condition
;
112 wxCondition::wxCondition()
114 p_internal
= new wxConditionInternal
;
115 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
118 wxCondition::~wxCondition()
120 pthread_cond_destroy(&(p_internal
->p_condition
));
124 void wxCondition::Wait(wxMutex
& mutex
)
126 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
129 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
131 struct timespec tspec
;
133 tspec
.tv_sec
= time(NULL
)+sec
;
134 tspec
.tv_nsec
= nsec
;
135 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
138 void wxCondition::Signal()
140 pthread_cond_signal(&(p_internal
->p_condition
));
143 void wxCondition::Broadcast()
145 pthread_cond_broadcast(&(p_internal
->p_condition
));
148 /////////////////////////////////////////////////////////////////////////////
149 // wxThread: Posix Thread implementation (Thread)
150 /////////////////////////////////////////////////////////////////////////////
152 class wxThreadInternal
{
154 wxThreadInternal() { state
= STATE_IDLE
; }
155 ~wxThreadInternal() {}
156 static void *PthreadStart(void *ptr
);
162 void *wxThreadInternal::PthreadStart(void *ptr
)
164 wxThread
*thread
= (wxThread
*)ptr
;
166 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
167 void* status
= thread
->Entry();
168 thread
->Exit(status
);
173 wxThreadError
wxThread::Create()
176 int min_prio
, max_prio
, p
;
177 struct sched_param sp
;
179 if (p_internal
->state
!= STATE_IDLE
)
180 return THREAD_RUNNING
;
182 // Change thread priority
183 pthread_attr_init(&a
);
184 pthread_attr_getschedpolicy(&a
, &p
);
186 min_prio
= sched_get_priority_min(p
);
187 max_prio
= sched_get_priority_max(p
);
189 pthread_attr_getschedparam(&a
, &sp
);
190 sp
.sched_priority
= min_prio
+
191 (p_internal
->prio
*(max_prio
-min_prio
))/100;
192 pthread_attr_setschedparam(&a
, &sp
);
194 // this is the point of no return
195 p_internal
->state
= STATE_RUNNING
;
196 if (pthread_create(&p_internal
->thread_id
, &a
,
197 wxThreadInternal::PthreadStart
, (void *)this) != 0) {
198 p_internal
->state
= STATE_IDLE
;
199 pthread_attr_destroy(&a
);
200 return THREAD_NO_RESOURCE
;
202 pthread_attr_destroy(&a
);
203 return THREAD_NO_ERROR
;
206 void wxThread::SetPriority(int prio
)
208 if (p_internal
->state
== STATE_RUNNING
)
215 p_internal
->prio
= prio
;
218 int wxThread::GetPriority() const
220 return p_internal
->prio
;
223 void wxThread::DeferDestroy(bool on
)
226 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
228 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
231 wxThreadError
wxThread::Destroy()
235 if (p_internal
->state
== STATE_RUNNING
) {
236 res
= pthread_cancel(p_internal
->thread_id
);
238 p_internal
->state
= STATE_CANCELED
;
240 return THREAD_NO_ERROR
;
243 void *wxThread::Join()
247 if (p_internal
->state
!= STATE_IDLE
) {
248 bool do_unlock
= wxThread::IsMain();
250 while (p_internal
->state
== STATE_RUNNING
)
254 wxMainMutex
.Unlock();
255 pthread_join(p_internal
->thread_id
, &status
);
258 p_internal
->state
= STATE_IDLE
;
263 unsigned long wxThread::GetID() const
265 return (unsigned long)p_internal
->thread_id
;
268 void wxThread::Exit(void *status
)
270 wxThread
* ptr
= this;
272 THREAD_SEND_EXIT_MSG(ptr
);
273 p_internal
->state
= STATE_EXITED
;
274 pthread_exit(status
);
277 void wxThread::TestDestroy()
279 pthread_testcancel();
282 bool wxThread::IsMain()
284 return (bool)pthread_equal(pthread_self(), p_mainid
);
289 p_internal
= new wxThreadInternal();
292 wxThread::~wxThread()
299 // The default callback just joins the thread and throws away the result.
300 void wxThread::OnExit()
304 // Automatic initialization
305 class wxThreadModule
: public wxModule
{
306 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
308 virtual bool OnInit() {
310 p_mainid
= pthread_self();
316 virtual void OnExit() {
317 wxMainMutex
.Unlock();
322 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)