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