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