]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/threadpsx.cpp
Compile fix for filefn.cpp
[wxWidgets.git] / src / gtk / threadpsx.cpp
CommitLineData
7c351dad
GL
1/////////////////////////////////////////////////////////////////////////////
2// Name: threadpsx.cpp
3// Purpose: wxThread (Posix) Implementation
4// Author: Original from Wolfram Gloger/Guilhem Lavaux
5// Modified by:
6// Created: 04/22/98
7// RCS-ID: $Id$
f3855ef0
RR
8// Copyright: (c) Wolfram Gloger (1996, 1997)
9// Guilhem Lavaux (1998)
10// Robert Roebling (1999)
7c351dad
GL
11// Licence: wxWindows licence
12/////////////////////////////////////////////////////////////////////////////
f3855ef0 13
7c351dad
GL
14#ifdef __GNUG__
15#pragma implementation "thread.h"
16#endif
17
18#include <stdio.h>
19#include <unistd.h>
7c351dad 20#include <pthread.h>
6163f5d8 21#include <errno.h>
82052aff
GL
22#include "wx/thread.h"
23#include "wx/module.h"
24#include "wx/utils.h"
3069ac4e 25#include "wx/log.h"
7c351dad 26
f3855ef0
RR
27enum thread_state
28{
7c351dad
GL
29 STATE_IDLE = 0,
30 STATE_RUNNING,
c2dd8380
GL
31 STATE_PAUSING,
32 STATE_PAUSED,
7c351dad
GL
33 STATE_CANCELED,
34 STATE_EXITED
35};
36
f3855ef0
RR
37//--------------------------------------------------------------------
38// global data
39//--------------------------------------------------------------------
7c351dad 40
7c351dad 41static pthread_t p_mainid;
c2dd8380 42
6773ae19 43wxMutex *wxMainMutex; // controls access to all GUI functions
7c351dad 44
f3855ef0
RR
45//--------------------------------------------------------------------
46// common GUI thread code
47//--------------------------------------------------------------------
48
7c351dad
GL
49#include "threadgui.inc"
50
f3855ef0
RR
51//--------------------------------------------------------------------
52// wxMutex (Posix implementation)
53//--------------------------------------------------------------------
7c351dad 54
f3855ef0
RR
55class wxMutexInternal
56{
7c351dad
GL
57public:
58 pthread_mutex_t p_mutex;
59};
60
ee4f8c2a 61wxMutex::wxMutex()
7c351dad 62{
f3855ef0
RR
63 p_internal = new wxMutexInternal;
64 pthread_mutex_init(&(p_internal->p_mutex), NULL);
65 m_locked = 0;
7c351dad
GL
66}
67
ee4f8c2a 68wxMutex::~wxMutex()
7c351dad 69{
f3855ef0
RR
70 if (m_locked > 0)
71 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked );
b89156b5 72
f3855ef0
RR
73 pthread_mutex_destroy(&(p_internal->p_mutex));
74 delete p_internal;
7c351dad
GL
75}
76
ee4f8c2a 77wxMutexError wxMutex::Lock()
7c351dad 78{
f3855ef0
RR
79 int err;
80
81 err = pthread_mutex_lock(&(p_internal->p_mutex));
82 if (err == EDEADLK)
b332090a 83 return wxMUTEX_DEAD_LOCK;
f3855ef0
RR
84
85 m_locked++;
b332090a 86 return wxMUTEX_NO_ERROR;
7c351dad
GL
87}
88
ee4f8c2a 89wxMutexError wxMutex::TryLock()
7c351dad 90{
f3855ef0
RR
91 int err;
92
93 if (m_locked)
b332090a 94 return wxMUTEX_BUSY;
f3855ef0
RR
95
96 err = pthread_mutex_trylock(&(p_internal->p_mutex));
97 switch (err)
98 {
b332090a 99 case EBUSY: return wxMUTEX_BUSY;
f3855ef0
RR
100 }
101 m_locked++;
b332090a 102 return wxMUTEX_NO_ERROR;
7c351dad
GL
103}
104
ee4f8c2a 105wxMutexError wxMutex::Unlock()
7c351dad 106{
f3855ef0
RR
107 if (m_locked > 0)
108 m_locked--;
109 else
b332090a 110 return wxMUTEX_UNLOCKED;
f3855ef0
RR
111
112 pthread_mutex_unlock(&(p_internal->p_mutex));
b332090a 113 return wxMUTEX_NO_ERROR;
7c351dad
GL
114}
115
f3855ef0
RR
116//--------------------------------------------------------------------
117// wxCondition (Posix implementation)
118//--------------------------------------------------------------------
7c351dad 119
f3855ef0
RR
120class wxConditionInternal
121{
7c351dad
GL
122public:
123 pthread_cond_t p_condition;
124};
125
ee4f8c2a 126wxCondition::wxCondition()
7c351dad 127{
f3855ef0
RR
128 p_internal = new wxConditionInternal;
129 pthread_cond_init(&(p_internal->p_condition), NULL);
7c351dad
GL
130}
131
ee4f8c2a 132wxCondition::~wxCondition()
7c351dad 133{
f3855ef0
RR
134 pthread_cond_destroy(&(p_internal->p_condition));
135 delete p_internal;
7c351dad
GL
136}
137
138void wxCondition::Wait(wxMutex& mutex)
139{
f3855ef0 140 pthread_cond_wait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex));
7c351dad
GL
141}
142
143bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec)
144{
f3855ef0 145 struct timespec tspec;
7c351dad 146
f3855ef0
RR
147 tspec.tv_sec = time(NULL)+sec;
148 tspec.tv_nsec = nsec;
149 return (pthread_cond_timedwait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex), &tspec) != ETIMEDOUT);
7c351dad
GL
150}
151
ee4f8c2a 152void wxCondition::Signal()
7c351dad 153{
f3855ef0 154 pthread_cond_signal(&(p_internal->p_condition));
7c351dad
GL
155}
156
ee4f8c2a 157void wxCondition::Broadcast()
7c351dad 158{
f3855ef0 159 pthread_cond_broadcast(&(p_internal->p_condition));
7c351dad
GL
160}
161
f3855ef0
RR
162//--------------------------------------------------------------------
163// wxThread (Posix implementation)
164//--------------------------------------------------------------------
7c351dad 165
f3855ef0
RR
166class wxThreadInternal
167{
7c351dad
GL
168public:
169 wxThreadInternal() { state = STATE_IDLE; }
170 ~wxThreadInternal() {}
171 static void *PthreadStart(void *ptr);
172 pthread_t thread_id;
173 int state;
174 int prio;
c2dd8380 175 int defer_destroy;
7c351dad
GL
176};
177
178void *wxThreadInternal::PthreadStart(void *ptr)
179{
f3855ef0 180 wxThread *thread = (wxThread *)ptr;
c2dd8380 181
f3855ef0
RR
182 // Call the main entry
183 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
184 void* status = thread->Entry();
c2dd8380 185
f3855ef0 186 thread->Exit(status);
7c351dad 187
f3855ef0 188 return NULL;
7c351dad
GL
189}
190
191wxThreadError wxThread::Create()
192{
f3855ef0
RR
193 pthread_attr_t a;
194 int min_prio, max_prio, p;
195 struct sched_param sp;
7c351dad 196
f3855ef0 197 if (p_internal->state != STATE_IDLE)
b332090a 198 return wxTHREAD_RUNNING;
7c351dad 199
f3855ef0
RR
200 // Change thread priority
201 pthread_attr_init(&a);
202 pthread_attr_getschedpolicy(&a, &p);
7c351dad 203
f3855ef0
RR
204 min_prio = sched_get_priority_min(p);
205 max_prio = sched_get_priority_max(p);
7c351dad 206
f3855ef0
RR
207 pthread_attr_getschedparam(&a, &sp);
208 sp.sched_priority = min_prio +
7c351dad 209 (p_internal->prio*(max_prio-min_prio))/100;
f3855ef0 210 pthread_attr_setschedparam(&a, &sp);
7c351dad 211
f3855ef0
RR
212 // this is the point of no return
213 p_internal->state = STATE_RUNNING;
214 if (pthread_create(&p_internal->thread_id, &a,
215 wxThreadInternal::PthreadStart, (void *)this) != 0)
216 {
217 p_internal->state = STATE_IDLE;
218 pthread_attr_destroy(&a);
b332090a 219 return wxTHREAD_NO_RESOURCE;
f3855ef0 220 }
7c351dad 221 pthread_attr_destroy(&a);
c2dd8380 222
b332090a 223 return wxTHREAD_NO_ERROR;
7c351dad
GL
224}
225
226void wxThread::SetPriority(int prio)
227{
f3855ef0
RR
228 if (p_internal->state == STATE_RUNNING)
229 return;
230
231 if (prio > 100) prio = 100;
232
233 if (prio < 0) prio = 0;
234
235 p_internal->prio = prio;
7c351dad
GL
236}
237
ee4f8c2a 238int wxThread::GetPriority() const
7c351dad 239{
f3855ef0 240 return p_internal->prio;
7c351dad
GL
241}
242
243void wxThread::DeferDestroy(bool on)
244{
f3855ef0
RR
245 if (on)
246 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
247 else
248 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
7c351dad
GL
249}
250
ee4f8c2a 251wxThreadError wxThread::Destroy()
7c351dad 252{
f3855ef0 253 int res = 0;
7c351dad 254
f3855ef0
RR
255 if (p_internal->state == STATE_RUNNING)
256 {
257 res = pthread_cancel(p_internal->thread_id);
258 if (res == 0)
259 p_internal->state = STATE_CANCELED;
260 }
c2dd8380 261
b332090a 262 return wxTHREAD_NO_ERROR;
c2dd8380
GL
263}
264
265wxThreadError wxThread::Pause()
266{
f3855ef0 267 if (p_internal->state != STATE_RUNNING)
b332090a 268 return wxTHREAD_NOT_RUNNING;
c2dd8380 269
f3855ef0 270 if (!p_internal->defer_destroy)
b332090a 271 return wxTHREAD_MISC_ERROR;
c2dd8380 272
f3855ef0 273 p_internal->state = STATE_PAUSING;
b332090a 274 return wxTHREAD_NO_ERROR;
c2dd8380
GL
275}
276
277wxThreadError wxThread::Resume()
278{
f3855ef0
RR
279 if (p_internal->state == STATE_PAUSING || p_internal->state == STATE_PAUSED)
280 p_internal->state = STATE_RUNNING;
c2dd8380 281
b332090a 282 return wxTHREAD_NO_ERROR;
7c351dad
GL
283}
284
285void *wxThread::Join()
286{
f3855ef0 287 void* status = 0;
7c351dad 288
f3855ef0
RR
289 if (p_internal->state != STATE_IDLE)
290 {
291 bool do_unlock = wxThread::IsMain();
7c351dad 292
f3855ef0
RR
293 while (p_internal->state == STATE_RUNNING)
294 wxYield();
c2dd8380 295
f3855ef0
RR
296 if (do_unlock) wxMainMutex->Unlock();
297
298 pthread_join(p_internal->thread_id, &status);
299
300 if (do_unlock) wxMainMutex->Lock();
c2dd8380 301
f3855ef0
RR
302 p_internal->state = STATE_IDLE;
303 }
304
305 return status;
7c351dad
GL
306}
307
ee4f8c2a 308unsigned long wxThread::GetID() const
7c351dad 309{
f3855ef0 310 return p_internal->thread_id;
7c351dad
GL
311}
312
313void wxThread::Exit(void *status)
314{
f3855ef0 315 wxThread* ptr = this;
7c351dad 316
f3855ef0
RR
317 THREAD_SEND_EXIT_MSG(ptr);
318 p_internal->state = STATE_EXITED;
319 pthread_exit(status);
7c351dad
GL
320}
321
322void wxThread::TestDestroy()
323{
f3855ef0
RR
324 if (p_internal->state == STATE_PAUSING)
325 {
326 p_internal->state = STATE_PAUSED;
327 while (p_internal->state == STATE_PAUSED)
328 {
329 pthread_testcancel();
330 usleep(1);
331 }
c2dd8380 332 }
f3855ef0 333 pthread_testcancel();
7c351dad
GL
334}
335
38009d39 336bool wxThread::IsMain()
7c351dad 337{
f3855ef0 338 return (bool)pthread_equal(pthread_self(), p_mainid);
7c351dad
GL
339}
340
c2dd8380
GL
341bool wxThread::IsRunning() const
342{
f3855ef0 343 return (p_internal->state == STATE_RUNNING);
c2dd8380
GL
344}
345
346bool wxThread::IsAlive() const
347{
f3855ef0
RR
348 return (p_internal->state == STATE_RUNNING) ||
349 (p_internal->state == STATE_PAUSING) ||
350 (p_internal->state == STATE_PAUSED);
c2dd8380
GL
351}
352
7c351dad
GL
353wxThread::wxThread()
354{
f3855ef0 355 p_internal = new wxThreadInternal();
7c351dad
GL
356}
357
358wxThread::~wxThread()
359{
f3855ef0
RR
360 Destroy();
361 Join();
362 delete p_internal;
7c351dad
GL
363}
364
365// The default callback just joins the thread and throws away the result.
366void wxThread::OnExit()
367{
f3855ef0 368 Join();
7c351dad
GL
369}
370
f3855ef0
RR
371//--------------------------------------------------------------------
372// wxThreadModule
373//--------------------------------------------------------------------
374
375class wxThreadModule : public wxModule
376{
7c351dad 377 DECLARE_DYNAMIC_CLASS(wxThreadModule)
f3855ef0 378
7c351dad 379public:
f3855ef0
RR
380 virtual bool OnInit()
381 {
382 wxMainMutex = new wxMutex();
383 wxThreadGuiInit();
384 p_mainid = pthread_self();
385 wxMainMutex->Lock();
386
387 return TRUE;
388 }
7c351dad 389
f3855ef0
RR
390 virtual void OnExit()
391 {
392 wxMainMutex->Unlock();
393 wxThreadGuiExit();
394 delete wxMainMutex;
7c351dad
GL
395 }
396};
397
398IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
f3855ef0 399