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 /////////////////////////////////////////////////////////////////////////////
31 #include "wx/thread.h"
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 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n",
63 pthread_mutex_destroy(&(p_internal
->p_mutex
));
67 wxMutexError
wxMutex::Lock()
71 err
= pthread_mutex_lock(&(p_internal
->p_mutex
));
73 return MUTEX_DEAD_LOCK
;
75 return MUTEX_NO_ERROR
;
78 wxMutexError
wxMutex::TryLock()
84 err
= pthread_mutex_trylock(&(p_internal
->p_mutex
));
86 case EBUSY
: return MUTEX_BUSY
;
89 return MUTEX_NO_ERROR
;
92 wxMutexError
wxMutex::Unlock()
97 return MUTEX_UNLOCKED
;
98 pthread_mutex_unlock(&(p_internal
->p_mutex
));
99 return MUTEX_NO_ERROR
;
102 /////////////////////////////////////////////////////////////////////////////
103 // wxThread: Posix Thread implementation (Condition)
104 /////////////////////////////////////////////////////////////////////////////
106 class wxConditionInternal
{
108 pthread_cond_t p_condition
;
111 wxCondition::wxCondition()
113 p_internal
= new wxConditionInternal
;
114 pthread_cond_init(&(p_internal
->p_condition
), NULL
);
117 wxCondition::~wxCondition()
119 pthread_cond_destroy(&(p_internal
->p_condition
));
123 void wxCondition::Wait(wxMutex
& mutex
)
125 pthread_cond_wait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
));
128 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
, unsigned long nsec
)
130 struct timespec tspec
;
132 tspec
.tv_sec
= time(NULL
)+sec
;
133 tspec
.tv_nsec
= nsec
;
134 return (pthread_cond_timedwait(&(p_internal
->p_condition
), &(mutex
.p_internal
->p_mutex
), &tspec
) != ETIMEDOUT
);
137 void wxCondition::Signal()
139 pthread_cond_signal(&(p_internal
->p_condition
));
142 void wxCondition::Broadcast()
144 pthread_cond_broadcast(&(p_internal
->p_condition
));
147 /////////////////////////////////////////////////////////////////////////////
148 // wxThread: Posix Thread implementation (Thread)
149 /////////////////////////////////////////////////////////////////////////////
151 class wxThreadInternal
{
153 wxThreadInternal() { state
= STATE_IDLE
; }
154 ~wxThreadInternal() {}
155 static void *PthreadStart(void *ptr
);
161 void *wxThreadInternal::PthreadStart(void *ptr
)
163 wxThread
*thread
= (wxThread
*)ptr
;
165 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
166 void* status
= thread
->Entry();
167 thread
->Exit(status
);
172 wxThreadError
wxThread::Create()
175 int min_prio
, max_prio
, p
;
176 struct sched_param sp
;
178 if (p_internal
->state
!= STATE_IDLE
)
179 return THREAD_RUNNING
;
181 // Change thread priority
182 pthread_attr_init(&a
);
183 pthread_attr_getschedpolicy(&a
, &p
);
185 min_prio
= sched_get_priority_min(p
);
186 max_prio
= sched_get_priority_max(p
);
188 pthread_attr_getschedparam(&a
, &sp
);
189 sp
.sched_priority
= min_prio
+
190 (p_internal
->prio
*(max_prio
-min_prio
))/100;
191 pthread_attr_setschedparam(&a
, &sp
);
193 // this is the point of no return
194 p_internal
->state
= STATE_RUNNING
;
195 if (pthread_create(&p_internal
->thread_id
, &a
,
196 wxThreadInternal::PthreadStart
, (void *)this) != 0) {
197 p_internal
->state
= STATE_IDLE
;
198 pthread_attr_destroy(&a
);
199 return THREAD_NO_RESOURCE
;
201 pthread_attr_destroy(&a
);
202 return THREAD_NO_ERROR
;
205 void wxThread::SetPriority(int prio
)
207 if (p_internal
->state
== STATE_RUNNING
)
214 p_internal
->prio
= prio
;
217 int wxThread::GetPriority() const
219 return p_internal
->prio
;
222 void wxThread::DeferDestroy(bool on
)
225 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED
, NULL
);
227 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
230 wxThreadError
wxThread::Destroy()
234 if (p_internal
->state
== STATE_RUNNING
) {
235 res
= pthread_cancel(p_internal
->thread_id
);
237 p_internal
->state
= STATE_CANCELED
;
239 return THREAD_NO_ERROR
;
242 void *wxThread::Join()
246 if (p_internal
->state
!= STATE_IDLE
) {
247 bool do_unlock
= wxThread::IsMain();
249 while (p_internal
->state
== STATE_RUNNING
)
253 wxMainMutex
.Unlock();
254 pthread_join(p_internal
->thread_id
, &status
);
257 p_internal
->state
= STATE_IDLE
;
262 unsigned long wxThread::GetID() const
264 return (unsigned long)p_internal
->thread_id
;
267 void wxThread::Exit(void *status
)
269 wxThread
* ptr
= this;
271 THREAD_SEND_EXIT_MSG(ptr
);
272 p_internal
->state
= STATE_EXITED
;
273 pthread_exit(status
);
276 void wxThread::TestDestroy()
278 pthread_testcancel();
281 bool wxThread::IsMain()
283 return (bool)pthread_equal(pthread_self(), p_mainid
);
288 p_internal
= new wxThreadInternal();
291 wxThread::~wxThread()
298 // The default callback just joins the thread and throws away the result.
299 void wxThread::OnExit()
303 // Automatic initialization
304 class wxThreadModule
: public wxModule
{
305 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
307 virtual bool OnInit() {
309 p_mainid
= pthread_self();
315 virtual void OnExit() {
316 wxMainMutex
.Unlock();
321 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)