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