Rewrite wxExecute() implementation under Unix.
[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 {
70 wxLogDebug( "wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked );
71 }
72 delete p_internal;
73 }
74
75 wxMutexError wxMutex::Lock()
76 {
77 spin_lock(&(p_internal->p_mutex));
78 m_locked++;
79 return wxMUTEX_NO_ERROR;
80 }
81
82 wxMutexError wxMutex::TryLock()
83 {
84 if (acquire_lock(&(p_internal->p_mutex)) != 0)
85 return wxMUTEX_BUSY;
86 m_locked++;
87 return wxMUTEX_NO_ERROR;
88 }
89
90 wxMutexError wxMutex::Unlock()
91 {
92 if (m_locked == 0)
93 return wxMUTEX_UNLOCKED;
94 release_lock(&(p_internal->p_mutex));
95 m_locked--;
96 return wxMUTEX_NO_ERROR;
97 }
98
99 // GL: Don't know how it works on SGI. Wolfram ?
100
101 wxCondition::wxCondition() {}
102 wxCondition::~wxCondition() {}
103 int wxCondition::Wait(wxMutex& WXUNUSED(mutex)) { return 0;}
104 int wxCondition::Wait(wxMutex& WXUNUSED(mutex), unsigned long WXUNUSED(sec),
105 unsigned long WXUNUSED(nsec)) { return 0; }
106 int wxCondition::Signal() { return 0; }
107 int wxCondition::Broadcast() { return 0; }
108
109 class
110 wxThreadPrivate {
111 public:
112 wxThreadPrivate() { thread_id = 0; state = STATE_IDLE; }
113 ~wxThreadPrivate() {}
114 static void SprocStart(void *ptr);
115 static void SignalHandler(int sig);
116 public:
117 int state, thread_id;
118 void* exit_status;
119 };
120
121 void wxThreadPrivate::SprocStart(void *ptr)
122 {
123 void* status;
124
125 wxThread *thr = (wxThread *)ptr;
126
127 thr->p_internal->thread_id = getpid();
128 thr->p_internal->exit_status = 0;
129 status = thr->Entry();
130 thr->Exit(status);
131 }
132
133 void wxThread::Exit(void* status)
134 {
135 wxThread* ptr = this;
136 THREAD_SEND_EXIT_MSG(ptr);
137 p_internal->state = STATE_EXITED;
138 p_internal->exit_status = status;
139 _exit(0);
140 }
141
142 wxThreadError wxThread::Create()
143 {
144 if (p_internal->state != STATE_IDLE)
145 return wxTHREAD_RUNNING;
146 p_internal->state = STATE_RUNNING;
147 if (sproc(p_internal->SprocStart, PR_SALL, this) < 0) {
148 p_internal->state = STATE_IDLE;
149 return wxTHREAD_NO_RESOURCE;
150 }
151 return wxTHREAD_NO_ERROR;
152 }
153
154 wxThreadError wxThread::Destroy()
155 {
156 if (p_internal->state == STATE_RUNNING)
157 p_internal->state = STATE_CANCELED;
158
159 return wxTHREAD_NO_ERROR;
160 }
161
162 wxThreadError wxThread::Pause()
163 {
164 return wxTHREAD_NO_ERROR;
165 }
166
167 wxThreadError wxThread::Resume()
168 {
169 return wxTHREAD_NO_ERROR;
170 }
171
172 void *wxThread::Join()
173 {
174 if (p_internal->state != STATE_IDLE) {
175 bool do_unlock = wxThread::IsMain();
176 int stat;
177
178 if (do_unlock)
179 wxMainMutex->Unlock();
180 waitpid(p_internal->thread_id, &stat, 0);
181 if (do_unlock)
182 wxMainMutex->Lock();
183 if (!WIFEXITED(stat) && !WIFSIGNALED(stat))
184 return 0;
185 p_internal->state = STATE_IDLE;
186 return p_internal->exit_status;
187 }
188 return 0;
189 }
190
191 unsigned long wxThread::GetID() const
192 {
193 return (unsigned long)p_internal->thread_id;
194 }
195
196 void wxThread::TestDestroy()
197 {
198 if (p_internal->state == STATE_CANCELED) {
199 p_internal->exit_status = 0;
200 _exit(0);
201 }
202 }
203
204 void wxThread::SetPriority(int prio)
205 {
206 }
207
208 int wxThread::GetPriority() const
209 {
210 return 0;
211 }
212
213 bool wxThread::IsMain()
214 {
215 return (int)getpid() == main_id;
216 }
217
218 bool wxThread::IsAlive() const
219 {
220 return (p_internal->state == STATE_RUNNING);
221 }
222
223 bool wxThread::IsRunning() const
224 {
225 return (p_internal->state == STATE_RUNNING);
226 }
227
228 wxThread::wxThread()
229 {
230 p_internal = new wxThreadPrivate();
231 }
232
233 wxThread::~wxThread()
234 {
235 Cancel();
236 Join();
237 delete p_internal;
238 }
239
240 // The default callback just joins the thread and throws away the result.
241 void wxThread::OnExit()
242 {
243 Join();
244 }
245
246 // Global initialization
247
248 class wxThreadModule : public wxModule
249 {
250 public:
251 virtual bool OnInit();
252 virtual void OnExit();
253
254 private:
255 DECLARE_DYNAMIC_CLASS(wxThreadModule)
256 };
257
258 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
259
260 bool wxThreadModule::OnInit()
261 {
262 wxMainMutex = new wxMutex();
263 wxThreadGuiInit();
264 p_mainid = (int)getpid();
265 wxMainMutex->Lock();
266 return true;
267 }
268
269 void wxThreadModule::OnExit()
270 {
271 wxMainMutex->Unlock();
272 wxThreadGuiExit();
273 delete wxMainMutex;
274 }