]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/threadpsx.cpp
Added #define wxHelpController to help.h; added wxWinHelpController::Quit code
[wxWidgets.git] / src / gtk1 / 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$
8// Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11#ifdef __GNUG__
12#pragma implementation "thread.h"
13#endif
14
15#include <stdio.h>
16#include <unistd.h>
17#include <sched.h>
18#include <pthread.h>
19
20enum thread_state {
21 STATE_IDLE = 0,
22 STATE_RUNNING,
23 STATE_CANCELED,
24 STATE_EXITED
25};
26
27/////////////////////////////////////////////////////////////////////////////
28// Static variables
29/////////////////////////////////////////////////////////////////////////////
30
31#include "thread.h"
32
33static pthread_t p_mainid;
34wxMutex wxMainMutex; // controls access to all GUI functions
35
36/////////////////////////////////////////////////////////////////////////////
37// GUI thread manager
38/////////////////////////////////////////////////////////////////////////////
39#include "threadgui.inc"
40
41/////////////////////////////////////////////////////////////////////////////
42// wxThread: Posix Thread implementation (Mutex)
43/////////////////////////////////////////////////////////////////////////////
44
45class wxMutexInternal {
46public:
47 pthread_mutex_t p_mutex;
48};
49
ee4f8c2a 50wxMutex::wxMutex()
7c351dad
GL
51{
52 p_internal = new wxMutexInternal;
53 pthread_mutex_init(&(p_internal->p_mutex), NULL);
b89156b5 54 m_locked = 0;
7c351dad
GL
55}
56
ee4f8c2a 57wxMutex::~wxMutex()
7c351dad 58{
b89156b5
GL
59 if (m_locked > 0)
60 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n",
61 m_locked);
62
7c351dad
GL
63 pthread_mutex_destroy(&(p_internal->p_mutex));
64 delete p_internal;
65}
66
ee4f8c2a 67wxMutexError wxMutex::Lock()
7c351dad
GL
68{
69 int err;
70
71 err = pthread_mutex_lock(&(p_internal->p_mutex));
b89156b5
GL
72 if (err == EDEADLK)
73 return MUTEX_DEAD_LOCK;
7c351dad
GL
74 m_locked++;
75 return MUTEX_NO_ERROR;
76}
77
ee4f8c2a 78wxMutexError wxMutex::TryLock()
7c351dad
GL
79{
80 int err;
81
82 if (m_locked)
83 return MUTEX_BUSY;
84 err = pthread_mutex_trylock(&(p_internal->p_mutex));
85 switch (err) {
86 case EBUSY: return MUTEX_BUSY;
87 }
88 m_locked++;
89 return MUTEX_NO_ERROR;
90}
91
ee4f8c2a 92wxMutexError wxMutex::Unlock()
7c351dad 93{
b89156b5
GL
94 if (m_locked > 0)
95 m_locked--;
96 else
97 return MUTEX_UNLOCKED;
7c351dad
GL
98 pthread_mutex_unlock(&(p_internal->p_mutex));
99 return MUTEX_NO_ERROR;
100}
101
102/////////////////////////////////////////////////////////////////////////////
103// wxThread: Posix Thread implementation (Condition)
104/////////////////////////////////////////////////////////////////////////////
105
106class wxConditionInternal {
107public:
108 pthread_cond_t p_condition;
109};
110
ee4f8c2a 111wxCondition::wxCondition()
7c351dad
GL
112{
113 p_internal = new wxConditionInternal;
114 pthread_cond_init(&(p_internal->p_condition), NULL);
115}
116
ee4f8c2a 117wxCondition::~wxCondition()
7c351dad
GL
118{
119 pthread_cond_destroy(&(p_internal->p_condition));
120 delete p_internal;
121}
122
123void wxCondition::Wait(wxMutex& mutex)
124{
125 pthread_cond_wait(&(p_internal->p_condition), &(mutex.p_internal->p_mutex));
126}
127
128bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec)
129{
130 struct timespec tspec;
131
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);
135}
136
ee4f8c2a 137void wxCondition::Signal()
7c351dad
GL
138{
139 pthread_cond_signal(&(p_internal->p_condition));
140}
141
ee4f8c2a 142void wxCondition::Broadcast()
7c351dad
GL
143{
144 pthread_cond_broadcast(&(p_internal->p_condition));
145}
146
147/////////////////////////////////////////////////////////////////////////////
148// wxThread: Posix Thread implementation (Thread)
149/////////////////////////////////////////////////////////////////////////////
150
151class wxThreadInternal {
152public:
153 wxThreadInternal() { state = STATE_IDLE; }
154 ~wxThreadInternal() {}
155 static void *PthreadStart(void *ptr);
156 pthread_t thread_id;
157 int state;
158 int prio;
159};
160
161void *wxThreadInternal::PthreadStart(void *ptr)
162{
163 wxThread *thread = (wxThread *)ptr;
164
165 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
166 void* status = thread->Entry();
167 thread->Exit(status);
168
169 return NULL;
170}
171
172wxThreadError wxThread::Create()
173{
174 pthread_attr_t a;
175 int min_prio, max_prio, p;
176 struct sched_param sp;
177
178 if (p_internal->state != STATE_IDLE)
179 return THREAD_RUNNING;
180
181 // Change thread priority
182 pthread_attr_init(&a);
183 pthread_attr_getschedpolicy(&a, &p);
184
185 min_prio = sched_get_priority_min(p);
186 max_prio = sched_get_priority_max(p);
187
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);
192
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;
200 }
201 pthread_attr_destroy(&a);
202 return THREAD_NO_ERROR;
203}
204
205void wxThread::SetPriority(int prio)
206{
207 if (p_internal->state == STATE_RUNNING)
208 return;
209
210 if (prio > 100)
211 prio = 100;
212 if (prio < 0)
213 prio = 0;
214 p_internal->prio = prio;
215}
216
ee4f8c2a 217int wxThread::GetPriority() const
7c351dad
GL
218{
219 return p_internal->prio;
220}
221
222void wxThread::DeferDestroy(bool on)
223{
224 if (on)
225 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
226 else
227 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
228}
229
ee4f8c2a 230wxThreadError wxThread::Destroy()
7c351dad
GL
231{
232 int res = 0;
233
234 if (p_internal->state == STATE_RUNNING) {
235 res = pthread_cancel(p_internal->thread_id);
236 if (res == 0)
237 p_internal->state = STATE_CANCELED;
238 }
239 return THREAD_NO_ERROR;
240}
241
242void *wxThread::Join()
243{
244 void* status = 0;
245
246 if (p_internal->state != STATE_IDLE) {
247 bool do_unlock = wxThread::IsMain();
248
249 while (p_internal->state == STATE_RUNNING)
250 wxYield();
251
252 if (do_unlock)
253 wxMainMutex.Unlock();
254 pthread_join(p_internal->thread_id, &status);
255 if (do_unlock)
256 wxMainMutex.Lock();
257 p_internal->state = STATE_IDLE;
258 }
259 return status;
260}
261
ee4f8c2a 262unsigned long wxThread::GetID() const
7c351dad
GL
263{
264 return (unsigned long)p_internal->thread_id;
265}
266
267void wxThread::Exit(void *status)
268{
269 wxThread* ptr = this;
270
271 THREAD_SEND_EXIT_MSG(ptr);
272 p_internal->state = STATE_EXITED;
273 pthread_exit(status);
274}
275
276void wxThread::TestDestroy()
277{
278 pthread_testcancel();
279}
280
ee4f8c2a 281bool wxThread::IsMain() const
7c351dad
GL
282{
283 return (bool)pthread_equal(pthread_self(), p_mainid);
284}
285
286wxThread::wxThread()
287{
288 p_internal = new wxThreadInternal();
289}
290
291wxThread::~wxThread()
292{
293 Destroy();
294 Join();
295 delete p_internal;
296}
297
298// The default callback just joins the thread and throws away the result.
299void wxThread::OnExit()
300{
301}
302
303// Automatic initialization
304class wxThreadModule : public wxModule {
305 DECLARE_DYNAMIC_CLASS(wxThreadModule)
306public:
ee4f8c2a 307 virtual bool OnInit() {
7c351dad
GL
308 wxThreadGuiInit();
309 p_mainid = pthread_self();
310 wxMainMutex.Lock();
311
312 return TRUE;
313 }
314
ee4f8c2a 315 virtual void OnExit() {
7c351dad
GL
316 wxMainMutex.Unlock();
317 wxThreadGuiExit();
318 }
319};
320
321IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)