use a common m_isInsideYield flag instead of static booleans in all ports; add a...
[wxWidgets.git] / src / gtk1 / threadsgi.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk1/threadsgi.cpp
3 // Purpose: wxThread (SGI) 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
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #include "wx/thread.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/log.h"
19 #include "wx/utils.h"
20 #include "wx/module.h"
21 #endif
22
23 #include <stdio.h>
24 #include <unistd.h>
25
26 #include <signal.h>
27 #include <sys/wait.h>
28 #include <sys/prctl.h>
29
30 #include "gdk/gdk.h"
31 #include "gtk/gtk.h"
32
33 enum thread_state
34 {
35 STATE_IDLE = 0,
36 STATE_RUNNING,
37 STATE_CANCELED,
38 STATE_EXITED
39 };
40
41 /////////////////////////////////////////////////////////////////////////////
42 // Static variables
43 /////////////////////////////////////////////////////////////////////////////
44
45 static int p_mainid;
46 wxMutex *wxMainMutex;
47
48 #include "threadgui.inc"
49
50 /////////////////////////////////////////////////////////////////////////////
51 // Unix implementations (SGI threads)
52 /////////////////////////////////////////////////////////////////////////////
53
54 class wxMutexInternal {
55 public:
56 abilock_t p_mutex;
57 };
58
59 wxMutex::wxMutex()
60 {
61 m_locked = 0;
62 p_internal = new wxMutexInternal;
63 init_lock(&(p_internal->p_mutex));
64 }
65
66 wxMutex::~wxMutex()
67 {
68 if (m_locked > 0)
69 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked );
70 delete p_internal;
71 }
72
73 wxMutexError wxMutex::Lock()
74 {
75 spin_lock(&(p_internal->p_mutex));
76 m_locked++;
77 return wxMUTEX_NO_ERROR;
78 }
79
80 wxMutexError wxMutex::TryLock()
81 {
82 if (acquire_lock(&(p_internal->p_mutex)) != 0)
83 return wxMUTEX_BUSY;
84 m_locked++;
85 return wxMUTEX_NO_ERROR;
86 }
87
88 wxMutexError wxMutex::Unlock()
89 {
90 if (m_locked == 0)
91 return wxMUTEX_UNLOCKED;
92 release_lock(&(p_internal->p_mutex));
93 m_locked--;
94 return wxMUTEX_NO_ERROR;
95 }
96
97 // GL: Don't know how it works on SGI. Wolfram ?
98
99 wxCondition::wxCondition() {}
100 wxCondition::~wxCondition() {}
101 int wxCondition::Wait(wxMutex& WXUNUSED(mutex)) { return 0;}
102 int wxCondition::Wait(wxMutex& WXUNUSED(mutex), unsigned long WXUNUSED(sec),
103 unsigned long WXUNUSED(nsec)) { return 0; }
104 int wxCondition::Signal() { return 0; }
105 int wxCondition::Broadcast() { return 0; }
106
107 class
108 wxThreadPrivate {
109 public:
110 wxThreadPrivate() { thread_id = 0; state = STATE_IDLE; }
111 ~wxThreadPrivate() {}
112 static void SprocStart(void *ptr);
113 static void SignalHandler(int sig);
114 public:
115 int state, thread_id;
116 void* exit_status;
117 };
118
119 void wxThreadPrivate::SprocStart(void *ptr)
120 {
121 void* status;
122
123 wxThread *thr = (wxThread *)ptr;
124
125 thr->p_internal->thread_id = getpid();
126 thr->p_internal->exit_status = 0;
127 status = thr->Entry();
128 thr->Exit(status);
129 }
130
131 void wxThread::Exit(void* status)
132 {
133 wxThread* ptr = this;
134 THREAD_SEND_EXIT_MSG(ptr);
135 p_internal->state = STATE_EXITED;
136 p_internal->exit_status = status;
137 _exit(0);
138 }
139
140 wxThreadError wxThread::Create()
141 {
142 if (p_internal->state != STATE_IDLE)
143 return wxTHREAD_RUNNING;
144 p_internal->state = STATE_RUNNING;
145 if (sproc(p_internal->SprocStart, PR_SALL, this) < 0) {
146 p_internal->state = STATE_IDLE;
147 return wxTHREAD_NO_RESOURCE;
148 }
149 return wxTHREAD_NO_ERROR;
150 }
151
152 wxThreadError wxThread::Destroy()
153 {
154 if (p_internal->state == STATE_RUNNING)
155 p_internal->state = STATE_CANCELED;
156
157 return wxTHREAD_NO_ERROR;
158 }
159
160 wxThreadError wxThread::Pause()
161 {
162 return wxTHREAD_NO_ERROR;
163 }
164
165 wxThreadError wxThread::Resume()
166 {
167 return wxTHREAD_NO_ERROR;
168 }
169
170 void *wxThread::Join()
171 {
172 if (p_internal->state != STATE_IDLE) {
173 bool do_unlock = wxThread::IsMain();
174 int stat;
175
176 if (do_unlock)
177 wxMainMutex->Unlock();
178 waitpid(p_internal->thread_id, &stat, 0);
179 if (do_unlock)
180 wxMainMutex->Lock();
181 if (!WIFEXITED(stat) && !WIFSIGNALED(stat))
182 return 0;
183 p_internal->state = STATE_IDLE;
184 return p_internal->exit_status;
185 }
186 return 0;
187 }
188
189 unsigned long wxThread::GetID() const
190 {
191 return (unsigned long)p_internal->thread_id;
192 }
193
194 void wxThread::TestDestroy()
195 {
196 if (p_internal->state == STATE_CANCELED) {
197 p_internal->exit_status = 0;
198 _exit(0);
199 }
200 }
201
202 void wxThread::SetPriority(int prio)
203 {
204 }
205
206 int wxThread::GetPriority() const
207 {
208 return 0;
209 }
210
211 bool wxThread::IsMain()
212 {
213 return (int)getpid() == main_id;
214 }
215
216 bool wxThread::IsAlive() const
217 {
218 return (p_internal->state == STATE_RUNNING);
219 }
220
221 bool wxThread::IsRunning() const
222 {
223 return (p_internal->state == STATE_RUNNING);
224 }
225
226 wxThread::wxThread()
227 {
228 p_internal = new wxThreadPrivate();
229 }
230
231 wxThread::~wxThread()
232 {
233 Cancel();
234 Join();
235 delete p_internal;
236 }
237
238 // The default callback just joins the thread and throws away the result.
239 void wxThread::OnExit()
240 {
241 Join();
242 }
243
244 // Global initialization
245
246 class wxThreadModule : public wxModule
247 {
248 public:
249 virtual bool OnInit();
250 virtual void OnExit();
251
252 private:
253 DECLARE_DYNAMIC_CLASS(wxThreadModule)
254 };
255
256 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
257
258 bool wxThreadModule::OnInit()
259 {
260 wxMainMutex = new wxMutex();
261 wxThreadGuiInit();
262 p_mainid = (int)getpid();
263 wxMainMutex->Lock();
264 return true;
265 }
266
267 void wxThreadModule::OnExit()
268 {
269 wxMainMutex->Unlock();
270 wxThreadGuiExit();
271 delete wxMainMutex;
272 }