1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxThread Implementation
4 // Author: Original from Wolfram Gloger/Guilhem Lavaux
8 // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "thread.h"
16 #include "wx/wxprec.h"
18 #if defined(__BORLANDC__)
29 #include "wx/module.h"
30 #include "wx/thread.h"
39 /////////////////////////////////////////////////////////////////////////////
41 /////////////////////////////////////////////////////////////////////////////
43 static HANDLE p_mainid
;
44 wxMutex wxMainMutex
; // controls access to all GUI functions
46 /////////////////////////////////////////////////////////////////////////////
47 // Windows implementation
48 /////////////////////////////////////////////////////////////////////////////
50 class wxMutexInternal
{
55 wxMutex::wxMutex(void)
57 p_internal
= new wxMutexInternal
;
58 p_internal
->p_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
62 wxMutex::~wxMutex(void)
64 CloseHandle(p_internal
->p_mutex
);
67 wxMutexError
wxMutex::Lock(void)
71 ret
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
);
72 if (ret
== WAIT_ABANDONED
)
76 return MUTEX_NO_ERROR
;
79 wxMutexError
wxMutex::TryLock(void)
83 ret
= WaitForSingleObject(p_internal
->p_mutex
, 0);
84 if (ret
== WAIT_TIMEOUT
|| ret
== WAIT_ABANDONED
)
88 return MUTEX_NO_ERROR
;
91 wxMutexError
wxMutex::Unlock(void)
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
;
104 class wxConditionInternal
{
110 wxCondition::wxCondition(void)
112 p_internal
= new wxConditionInternal
;
113 p_internal
->event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
114 p_internal
->waiters
= 0;
117 wxCondition::~wxCondition(void)
119 CloseHandle(p_internal
->event
);
122 void wxCondition::Wait(wxMutex
& mutex
)
125 p_internal
->waiters
++;
126 WaitForSingleObject(p_internal
->event
, INFINITE
);
127 p_internal
->waiters
--;
131 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
,
137 p_internal
->waiters
++;
138 ret
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000));
139 p_internal
->waiters
--;
142 return (ret
!= WAIT_TIMEOUT
);
145 void wxCondition::Signal(void)
147 SetEvent(p_internal
->event
);
150 void wxCondition::Broadcast(void)
154 for (i
=0;i
<p_internal
->waiters
;i
++)
155 SetEvent(p_internal
->event
);
158 class wxThreadInternal
{
160 static DWORD
WinThreadStart(LPVOID arg
);
168 DWORD
wxThreadInternal::WinThreadStart(LPVOID arg
)
170 wxThread
*ptr
= (wxThread
*)arg
;
173 ret
= (DWORD
)ptr
->Entry();
174 ptr
->p_internal
->state
= STATE_EXITED
;
179 wxThreadError
wxThread::Create(void)
181 int win_prio
, prio
= p_internal
->prio
;
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
;
192 win_prio
= THREAD_PRIORITY_LOWEST
;
194 win_prio
= THREAD_PRIORITY_BELOW_NORMAL
;
196 win_prio
= THREAD_PRIORITY_NORMAL
;
198 win_prio
= THREAD_PRIORITY_ABOVE_NORMAL
;
199 else if (prio
<= 100)
200 win_prio
= THREAD_PRIORITY_HIGHEST
;
202 SetThreadPriority(p_internal
->thread_id
, win_prio
);
204 ResumeThread(p_internal
->thread_id
);
205 p_internal
->state
= STATE_RUNNING
;
207 return THREAD_NO_ERROR
;
210 wxThreadError
wxThread::Destroy()
212 if (p_internal
->state
!= STATE_RUNNING
)
213 return THREAD_NOT_RUNNING
;
215 if (p_internal
->defer
== FALSE
)
216 TerminateThread(p_internal
->thread_id
, 0);
218 p_internal
->state
= STATE_CANCELED
;
220 return THREAD_NO_ERROR
;
223 void wxThread::Exit(void *status
)
225 p_internal
->state
= STATE_EXITED
;
226 ExitThread((DWORD
)status
);
229 void wxThread::SetPriority(int prio
)
231 p_internal
->prio
= prio
;
234 int wxThread::GetPriority(void)
236 return p_internal
->prio
;
239 void wxThread::DeferDestroy(bool on
)
241 p_internal
->defer
= on
;
244 void wxThread::TestDestroy()
246 if (p_internal
->state
== STATE_CANCELED
)
250 void *wxThread::Join()
254 if (p_internal
->state
== STATE_IDLE
)
257 if (wxThread::IsMain())
258 wxMainMutex
.Unlock();
259 WaitForSingleObject(p_internal
->thread_id
, INFINITE
);
260 if (wxThread::IsMain())
263 GetExitCodeThread(p_internal
->thread_id
, &exit_code
);
264 CloseHandle(p_internal
->thread_id
);
266 p_internal
->state
= STATE_IDLE
;
268 return (void *)exit_code
;
271 unsigned long wxThread::GetID()
273 return (unsigned long)p_internal
->tid
;
276 bool wxThread::IsMain()
278 return (GetCurrentThread() == p_mainid
);
283 p_internal
= new wxThreadInternal();
285 p_internal
->defer
= FALSE
;
286 p_internal
->prio
= WXTHREAD_DEFAULT_PRIORITY
;
287 p_internal
->state
= STATE_IDLE
;
290 wxThread::~wxThread()
297 // The default callback just joins the thread and throws away the result.
298 void wxThread::OnExit()
303 // Automatic initialization
304 class wxThreadModule
: public wxModule
{
305 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
307 virtual bool OnInit(void) {
308 p_mainid
= GetCurrentThread();
314 virtual void OnExit(void) {
315 wxMainMutex
.Unlock();
319 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)