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