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