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"
27 /////////////////////////////////////////////////////////////////////////////
29 /////////////////////////////////////////////////////////////////////////////
33 static pthread_t p_mainid
;
34 wxMutex wxMainMutex
; // controls access to all GUI functions
36 /////////////////////////////////////////////////////////////////////////////
38 /////////////////////////////////////////////////////////////////////////////
39 #include "threadgui.inc"
41 /////////////////////////////////////////////////////////////////////////////
42 // wxThread: Posix Thread implementation (Mutex)
43 /////////////////////////////////////////////////////////////////////////////
45 class wxMutexInternal
{
47 pthread_mutex_t p_mutex
;
52 p_internal
= new wxMutexInternal
;
53 pthread_mutex_init(&(p_internal
->p_mutex
), NULL
);
60 pthread_mutex_unlock(&(p_internal
->p_mutex
));
61 pthread_mutex_destroy(&(p_internal
->p_mutex
));
65 wxMutexError
wxMutex::Lock()
69 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
71 case EDEADLK
: return MUTEX_DEAD_LOCK
;
74 return MUTEX_NO_ERROR
;
77 wxMutexError
wxMutex::TryLock()
83 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
85 case EBUSY
: return MUTEX_BUSY
;
88 return MUTEX_NO_ERROR
;
91 wxMutexError
wxMutex::Unlock()
93 if (m_locked
> 0) m_locked
--;
94 pthread_mutex_unlock(&(p_internal
->p_mutex
));
95 return MUTEX_NO_ERROR
;
98 /////////////////////////////////////////////////////////////////////////////
99 // wxThread: Posix Thread implementation (Condition)
100 /////////////////////////////////////////////////////////////////////////////
102 class wxConditionInternal
{
104 pthread_cond_t p_condition
;
107 wxCondition::wxCondition()
109 p_internal
= new wxConditionInternal
;
110 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
113 wxCondition::~wxCondition()
115 pthread_cond_destroy(&(p_internal
->p_condition
));
119 void wxCondition::Wait(wxMutex
& mutex
)
121 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
124 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
126 struct timespec tspec
;
128 tspec
.tv_sec
= time(NULL
)+sec
;
129 tspec
.tv_nsec
= nsec
;
130 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
133 void wxCondition::Signal()
135 pthread_cond_signal(&(p_internal
->p_condition
));
138 void wxCondition::Broadcast()
140 pthread_cond_broadcast(&(p_internal
->p_condition
));
143 /////////////////////////////////////////////////////////////////////////////
144 // wxThread: Posix Thread implementation (Thread)
145 /////////////////////////////////////////////////////////////////////////////
147 class wxThreadInternal
{
149 wxThreadInternal() { state
= STATE_IDLE
; }
150 ~wxThreadInternal() {}
151 static void *PthreadStart(void *ptr
);
157 void *wxThreadInternal::PthreadStart(void *ptr
)
159 wxThread
*thread
= (wxThread
*)ptr
;
161 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
162 void* status
= thread
->Entry();
163 thread
->Exit(status
);
168 wxThreadError
wxThread::Create()
171 int min_prio
, max_prio
, p
;
172 struct sched_param sp
;
174 if (p_internal
->state
!= STATE_IDLE
)
175 return THREAD_RUNNING
;
177 // Change thread priority
178 pthread_attr_init(&a
);
179 pthread_attr_getschedpolicy(&a
, &p
);
181 min_prio
= sched_get_priority_min(p
);
182 max_prio
= sched_get_priority_max(p
);
184 pthread_attr_getschedparam(&a
, &sp
);
185 sp
.sched_priority
= min_prio
+
186 (p_internal
->prio
*(max_prio
-min_prio
))/100;
187 pthread_attr_setschedparam(&a
, &sp
);
189 // this is the point of no return
190 p_internal
->state
= STATE_RUNNING
;
191 if (pthread_create(&p_internal
->thread_id
, &a
,
192 wxThreadInternal::PthreadStart
, (void *)this) != 0) {
193 p_internal
->state
= STATE_IDLE
;
194 pthread_attr_destroy(&a
);
195 return THREAD_NO_RESOURCE
;
197 pthread_attr_destroy(&a
);
198 return THREAD_NO_ERROR
;
201 void wxThread::SetPriority(int prio
)
203 if (p_internal
->state
== STATE_RUNNING
)
210 p_internal
->prio
= prio
;
213 int wxThread::GetPriority() const
215 return p_internal
->prio
;
218 void wxThread::DeferDestroy(bool on
)
221 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
223 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
226 wxThreadError
wxThread::Destroy()
230 if (p_internal
->state
== STATE_RUNNING
) {
231 res
= pthread_cancel(p_internal
->thread_id
);
233 p_internal
->state
= STATE_CANCELED
;
235 return THREAD_NO_ERROR
;
238 void *wxThread::Join()
242 if (p_internal
->state
!= STATE_IDLE
) {
243 bool do_unlock
= wxThread::IsMain();
245 while (p_internal
->state
== STATE_RUNNING
)
249 wxMainMutex
.Unlock();
250 pthread_join(p_internal
->thread_id
, &status
);
253 p_internal
->state
= STATE_IDLE
;
258 unsigned long wxThread::GetID() const
260 return (unsigned long)p_internal
->thread_id
;
263 void wxThread::Exit(void *status
)
265 wxThread
* ptr
= this;
267 THREAD_SEND_EXIT_MSG(ptr
);
268 p_internal
->state
= STATE_EXITED
;
269 pthread_exit(status
);
272 void wxThread::TestDestroy()
274 pthread_testcancel();
277 bool wxThread::IsMain() const
279 return (bool)pthread_equal(pthread_self(), p_mainid
);
284 p_internal
= new wxThreadInternal();
287 wxThread::~wxThread()
294 // The default callback just joins the thread and throws away the result.
295 void wxThread::OnExit()
299 // Automatic initialization
300 class wxThreadModule
: public wxModule
{
301 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
303 virtual bool OnInit() {
305 p_mainid
= pthread_self();
311 virtual void OnExit() {
312 wxMainMutex
.Unlock();
317 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)