* Corrected #include "thread.h" => #include "wx/thread.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
22 enum thread_state {
23 STATE_IDLE = 0,
24 STATE_RUNNING,
25 STATE_CANCELED,
26 STATE_EXITED
27 };
28
29 /////////////////////////////////////////////////////////////////////////////
30 // Static variables
31 /////////////////////////////////////////////////////////////////////////////
32
33 #include "wx/thread.h"
34
35 static int p_mainid;
36 wxMutex wxMainMutex;
37
38 #include "threadgui.inc"
39
40 /////////////////////////////////////////////////////////////////////////////
41 // Unix implementations (SGI threads)
42 /////////////////////////////////////////////////////////////////////////////
43
44 class wxMutexInternal {
45 public:
46 abilock_t p_mutex;
47 };
48
49 wxMutex::wxMutex()
50 {
51 m_locked = 0;
52 p_internal = new wxMutexInternal;
53 init_lock(&(p_internal->p_mutex));
54 }
55
56 wxMutex::~wxMutex()
57 {
58 if (m_locked > 0)
59 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n",
60 m_locked);
61 delete p_internal;
62 }
63
64 wxMutexError wxMutex::Lock()
65 {
66 spin_lock(&(p_internal->p_mutex));
67 m_locked++;
68 return MUTEX_NO_ERROR;
69 }
70
71 wxMutexError wxMutex::TryLock()
72 {
73 if (acquire_lock(&(p_internal->p_mutex)) != 0)
74 return MUTEX_BUSY;
75 m_locked++;
76 return MUTEX_NO_ERROR;
77 }
78
79 wxMutexError wxMutex::Unlock()
80 {
81 if (m_locked == 0)
82 return MUTEX_UNLOCKED;
83 release_lock(&(p_internal->p_mutex));
84 m_locked--;
85 return MUTEX_NO_ERROR;
86 }
87
88 // GL: Don't know how it works on SGI. Wolfram ?
89
90 wxCondition::wxCondition() {}
91 wxCondition::~wxCondition() {}
92 int wxCondition::Wait(wxMutex& WXUNUSED(mutex)) { return 0;}
93 int wxCondition::Wait(wxMutex& WXUNUSED(mutex), unsigned long WXUNUSED(sec),
94 unsigned long WXUNUSED(nsec)) { return 0; }
95 int wxCondition::Signal() { return 0; }
96 int wxCondition::Broadcast() { return 0; }
97
98 class
99 wxThreadPrivate {
100 public:
101 wxThreadPrivate() { thread_id = 0; state = STATE_IDLE; }
102 ~wxThreadPrivate() {}
103 static void SprocStart(void *ptr);
104 static void SignalHandler(int sig);
105 public:
106 int state, thread_id;
107 void* exit_status;
108 };
109
110 void wxThreadPrivate::SprocStart(void *ptr)
111 {
112 void* status;
113
114 wxThread *thr = (wxThread *)ptr;
115
116 thr->p_internal->thread_id = getpid();
117 thr->p_internal->exit_status = 0;
118 status = thr->Entry();
119 thr->Exit(status);
120 }
121
122 void wxThread::Exit(void* status)
123 {
124 wxThread* ptr = this;
125 THREAD_SEND_EXIT_MSG(ptr);
126 p_internal->state = STATE_EXITED;
127 p_internal->exit_status = status;
128 _exit(0);
129 }
130
131 wxThreadError wxThread::Create()
132 {
133 if (p_internal->state != STATE_IDLE)
134 return THREAD_RUNNING;
135 p_internal->state = STATE_RUNNING;
136 if (sproc(p_internal->SprocStart, PR_SALL, this) < 0) {
137 p_internal->state = STATE_IDLE;
138 return THREAD_NO_RESOURCE;
139 }
140 return THREAD_NO_ERROR;
141 }
142
143 void wxThread::Destroy()
144 {
145 if (p_internal->state == STATE_RUNNING)
146 p_internal->state = STATE_CANCELED;
147 }
148
149 void *wxThread::Join()
150 {
151 if (p_internal->state != STATE_IDLE) {
152 bool do_unlock = wxThread::IsMain();
153 int stat;
154
155 if (do_unlock)
156 wxMainMutex.Unlock();
157 waitpid(p_internal->thread_id, &stat, 0);
158 if (do_unlock)
159 wxMainMutex.Lock();
160 if (!WIFEXITED(stat) && !WIFSIGNALED(stat))
161 return 0;
162 p_internal->state = STATE_IDLE;
163 return p_internal->exit_status;
164 }
165 return 0;
166 }
167
168 unsigned long wxThread::GetID() const
169 {
170 return (unsigned long)p_internal->thread_id;
171 }
172
173 void wxThread::TestDestroy()
174 {
175 if (p_internal->state == STATE_CANCELED) {
176 p_internal->exit_status = 0;
177 _exit(0);
178 }
179 }
180
181 void wxThread::SetPriority(int prio)
182 {
183 }
184
185 int wxThread::GetPriority() const
186 {
187 return 0;
188 }
189
190 bool wxThreadIsMain()
191 {
192 return (int)getpid() == main_id;
193 }
194
195 wxThread::wxThread()
196 {
197 p_internal = new wxThreadPrivate();
198 }
199
200 wxThread::~wxThread()
201 {
202 Cancel();
203 Join();
204 delete p_internal;
205 }
206
207 // The default callback just joins the thread and throws away the result.
208 void wxThread::OnExit()
209 {
210 Join();
211 }
212
213 // Global initialization
214 class wxThreadModule : public wxModule {
215 DECLARE_DYNAMIC_CLASS(wxThreadModule)
216 public:
217 virtual bool OnInit() {
218 wxThreadGuiInit();
219 p_mainid = (int)getpid();
220 wxMainMutex.Lock();
221 }
222
223 virtual void OnExit() {
224 wxMainMutex.Unlock();
225 wxThreadGuiExit();
226 }
227 };
228
229 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)