]> git.saurik.com Git - wxWidgets.git/blame - src/msw/thread.cpp
wxWindow::FindFocus() doesn't exist in wxGTK - #ifdef'd out
[wxWidgets.git] / src / msw / thread.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: thread.cpp
3// Purpose: wxThread 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#ifdef __GNUG__
13#pragma implementation "thread.h"
14#endif
15
16#include "wx/wxprec.h"
17
18#if defined(__BORLANDC__)
19#pragma hdrstop
20#endif
21
22#ifndef WX_PRECOMP
23#include "wx/wx.h"
24#endif
25
26#include <stdio.h>
27
28#include <windows.h>
29#include "wx/module.h"
30#include "wx/thread.h"
31
32enum thread_state {
33 STATE_IDLE = 0,
34 STATE_RUNNING,
35 STATE_CANCELED,
36 STATE_EXITED
37};
38
39/////////////////////////////////////////////////////////////////////////////
40// Static variables
41/////////////////////////////////////////////////////////////////////////////
42
43static HANDLE p_mainid;
44wxMutex wxMainMutex; // controls access to all GUI functions
45
46/////////////////////////////////////////////////////////////////////////////
47// Windows implementation
48/////////////////////////////////////////////////////////////////////////////
49
50class wxMutexInternal {
51public:
52 HANDLE p_mutex;
53};
54
ee4f8c2a 55wxMutex::wxMutex()
2bda0e17
KB
56{
57 p_internal = new wxMutexInternal;
58 p_internal->p_mutex = CreateMutex(NULL, FALSE, NULL);
59 m_locked = 0;
60}
61
ee4f8c2a 62wxMutex::~wxMutex()
2bda0e17 63{
b89156b5
GL
64 if (m_locked > 0)
65 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked);
2bda0e17
KB
66 CloseHandle(p_internal->p_mutex);
67}
68
ee4f8c2a 69wxMutexError wxMutex::Lock()
2bda0e17
KB
70{
71 DWORD ret;
72
73 ret = WaitForSingleObject(p_internal->p_mutex, INFINITE);
74 if (ret == WAIT_ABANDONED)
75 return MUTEX_BUSY;
76
77 m_locked++;
78 return MUTEX_NO_ERROR;
79}
80
ee4f8c2a 81wxMutexError wxMutex::TryLock()
2bda0e17
KB
82{
83 DWORD ret;
84
85 ret = WaitForSingleObject(p_internal->p_mutex, 0);
86 if (ret == WAIT_TIMEOUT || ret == WAIT_ABANDONED)
87 return MUTEX_BUSY;
88
89 m_locked++;
90 return MUTEX_NO_ERROR;
91}
92
ee4f8c2a 93wxMutexError wxMutex::Unlock()
2bda0e17
KB
94{
95 BOOL ret;
96
97 if (m_locked > 0)
98 m_locked--;
99
100 // Why does this have 3 args? The redundant ones removed by JACS
101// ret = ReleaseMutex(p_internal->p_mutex, 1, NULL);
102 ret = ReleaseMutex(p_internal->p_mutex);
103 return MUTEX_NO_ERROR;
104}
105
106class wxConditionInternal {
107public:
108 HANDLE event;
109 int waiters;
110};
111
ee4f8c2a 112wxCondition::wxCondition()
2bda0e17
KB
113{
114 p_internal = new wxConditionInternal;
115 p_internal->event = CreateEvent(NULL, FALSE, FALSE, NULL);
116 p_internal->waiters = 0;
117}
118
ee4f8c2a 119wxCondition::~wxCondition()
2bda0e17
KB
120{
121 CloseHandle(p_internal->event);
122}
123
124void wxCondition::Wait(wxMutex& mutex)
125{
126 mutex.Unlock();
127 p_internal->waiters++;
128 WaitForSingleObject(p_internal->event, INFINITE);
129 p_internal->waiters--;
130 mutex.Lock();
131}
132
133bool wxCondition::Wait(wxMutex& mutex, unsigned long sec,
134 unsigned long nsec)
135{
136 DWORD ret;
137
138 mutex.Unlock();
139 p_internal->waiters++;
140 ret = WaitForSingleObject(p_internal->event, (sec*1000)+(nsec/1000000));
141 p_internal->waiters--;
142 mutex.Lock();
143
144 return (ret != WAIT_TIMEOUT);
145}
146
ee4f8c2a 147void wxCondition::Signal()
2bda0e17
KB
148{
149 SetEvent(p_internal->event);
150}
151
ee4f8c2a 152void wxCondition::Broadcast()
2bda0e17
KB
153{
154 int i;
155
156 for (i=0;i<p_internal->waiters;i++)
157 SetEvent(p_internal->event);
158}
159
160class wxThreadInternal {
161public:
162 static DWORD WinThreadStart(LPVOID arg);
163
164 HANDLE thread_id;
165 int state;
166 int prio, defer;
167 DWORD tid;
168};
169
170DWORD wxThreadInternal::WinThreadStart(LPVOID arg)
171{
172 wxThread *ptr = (wxThread *)arg;
173 DWORD ret;
174
175 ret = (DWORD)ptr->Entry();
176 ptr->p_internal->state = STATE_EXITED;
177
178 return ret;
179}
180
ee4f8c2a 181wxThreadError wxThread::Create()
2bda0e17
KB
182{
183 int win_prio, prio = p_internal->prio;
184
185 p_internal->thread_id = CreateThread(NULL, 0,
186 (LPTHREAD_START_ROUTINE)wxThreadInternal::WinThreadStart,
187 (void *)this, CREATE_SUSPENDED, &p_internal->tid);
188 if (p_internal->thread_id == NULL) {
189 printf("Error = %d\n", GetLastError());
190 return THREAD_NO_RESOURCE;
191 }
192
193 if (prio <= 20)
194 win_prio = THREAD_PRIORITY_LOWEST;
195 else if (prio <= 40)
196 win_prio = THREAD_PRIORITY_BELOW_NORMAL;
197 else if (prio <= 60)
198 win_prio = THREAD_PRIORITY_NORMAL;
199 else if (prio <= 80)
200 win_prio = THREAD_PRIORITY_ABOVE_NORMAL;
201 else if (prio <= 100)
202 win_prio = THREAD_PRIORITY_HIGHEST;
203
204 SetThreadPriority(p_internal->thread_id, win_prio);
205
206 ResumeThread(p_internal->thread_id);
207 p_internal->state = STATE_RUNNING;
208
209 return THREAD_NO_ERROR;
210}
211
212wxThreadError wxThread::Destroy()
213{
214 if (p_internal->state != STATE_RUNNING)
215 return THREAD_NOT_RUNNING;
216
217 if (p_internal->defer == FALSE)
218 TerminateThread(p_internal->thread_id, 0);
219 else
220 p_internal->state = STATE_CANCELED;
221
222 return THREAD_NO_ERROR;
223}
224
225void wxThread::Exit(void *status)
226{
227 p_internal->state = STATE_EXITED;
228 ExitThread((DWORD)status);
229}
230
231void wxThread::SetPriority(int prio)
232{
233 p_internal->prio = prio;
234}
235
38009d39 236int wxThread::GetPriority() const
2bda0e17
KB
237{
238 return p_internal->prio;
239}
240
241void wxThread::DeferDestroy(bool on)
242{
243 p_internal->defer = on;
244}
245
246void wxThread::TestDestroy()
247{
248 if (p_internal->state == STATE_CANCELED)
249 ExitThread(0);
250}
251
252void *wxThread::Join()
253{
254 DWORD exit_code;
255
256 if (p_internal->state == STATE_IDLE)
257 return NULL;
258
259 if (wxThread::IsMain())
260 wxMainMutex.Unlock();
261 WaitForSingleObject(p_internal->thread_id, INFINITE);
262 if (wxThread::IsMain())
263 wxMainMutex.Lock();
264
265 GetExitCodeThread(p_internal->thread_id, &exit_code);
266 CloseHandle(p_internal->thread_id);
267
268 p_internal->state = STATE_IDLE;
269
270 return (void *)exit_code;
271}
272
ee4f8c2a 273unsigned long wxThread::GetID() const
2bda0e17
KB
274{
275 return (unsigned long)p_internal->tid;
276}
277
38009d39 278bool wxThread::IsMain()
2bda0e17
KB
279{
280 return (GetCurrentThread() == p_mainid);
281}
282
283wxThread::wxThread()
284{
285 p_internal = new wxThreadInternal();
286
287 p_internal->defer = FALSE;
288 p_internal->prio = WXTHREAD_DEFAULT_PRIORITY;
289 p_internal->state = STATE_IDLE;
290}
291
292wxThread::~wxThread()
293{
294 Destroy();
295 Join();
296 delete p_internal;
297}
298
299// The default callback just joins the thread and throws away the result.
300void wxThread::OnExit()
301{
302 Join();
303}
304
305// Automatic initialization
306class wxThreadModule : public wxModule {
307 DECLARE_DYNAMIC_CLASS(wxThreadModule)
308public:
ee4f8c2a 309 virtual bool OnInit() {
2bda0e17
KB
310 p_mainid = GetCurrentThread();
311 wxMainMutex.Lock();
312 return TRUE;
313 }
314
315 // Global cleanup
ee4f8c2a 316 virtual void OnExit() {
2bda0e17
KB
317 wxMainMutex.Unlock();
318 }
319};
320
321IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
322