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 // this is here to regen the precompiled header in the ide compile otherwise the
17 // compiler crashes in vc5 (nfi why)
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
21 #if defined(__BORLANDC__)
32 #include "wx/module.h"
33 #include "wx/thread.h"
42 /////////////////////////////////////////////////////////////////////////////
44 /////////////////////////////////////////////////////////////////////////////
46 static HANDLE p_mainid
;
47 wxMutex wxMainMutex
; // controls access to all GUI functions
49 /////////////////////////////////////////////////////////////////////////////
50 // Windows implementation
51 /////////////////////////////////////////////////////////////////////////////
53 class wxMutexInternal
{
60 p_internal
= new wxMutexInternal
;
61 p_internal
->p_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
68 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
69 CloseHandle(p_internal
->p_mutex
);
72 wxMutexError
wxMutex::Lock()
76 ret
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
);
77 if (ret
== WAIT_ABANDONED
)
81 return MUTEX_NO_ERROR
;
84 wxMutexError
wxMutex::TryLock()
88 ret
= WaitForSingleObject(p_internal
->p_mutex
, 0);
89 if (ret
== WAIT_TIMEOUT
|| ret
== WAIT_ABANDONED
)
93 return MUTEX_NO_ERROR
;
96 wxMutexError
wxMutex::Unlock()
103 // Why does this have 3 args? The redundant ones removed by JACS
104 // ret = ReleaseMutex(p_internal->p_mutex, 1, NULL);
105 ret
= ReleaseMutex(p_internal
->p_mutex
);
106 return MUTEX_NO_ERROR
;
109 class wxConditionInternal
{
115 wxCondition::wxCondition()
117 p_internal
= new wxConditionInternal
;
118 p_internal
->event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
119 p_internal
->waiters
= 0;
122 wxCondition::~wxCondition()
124 CloseHandle(p_internal
->event
);
127 void wxCondition::Wait(wxMutex
& mutex
)
130 p_internal
->waiters
++;
131 WaitForSingleObject(p_internal
->event
, INFINITE
);
132 p_internal
->waiters
--;
136 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
,
142 p_internal
->waiters
++;
143 ret
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000));
144 p_internal
->waiters
--;
147 return (ret
!= WAIT_TIMEOUT
);
150 void wxCondition::Signal()
152 SetEvent(p_internal
->event
);
155 void wxCondition::Broadcast()
159 for (i
=0;i
<p_internal
->waiters
;i
++)
160 SetEvent(p_internal
->event
);
163 class wxThreadInternal
{
165 static DWORD
WinThreadStart(LPVOID arg
);
173 DWORD
wxThreadInternal::WinThreadStart(LPVOID arg
)
175 wxThread
*ptr
= (wxThread
*)arg
;
178 ret
= (DWORD
)ptr
->Entry();
179 ptr
->p_internal
->state
= STATE_EXITED
;
184 wxThreadError
wxThread::Create()
186 int win_prio
, prio
= p_internal
->prio
;
188 p_internal
->thread_id
= CreateThread(NULL
, 0,
189 (LPTHREAD_START_ROUTINE
)wxThreadInternal::WinThreadStart
,
190 (void *)this, CREATE_SUSPENDED
, &p_internal
->tid
);
191 if (p_internal
->thread_id
== NULL
) {
192 printf("Error = %d\n", GetLastError());
193 return THREAD_NO_RESOURCE
;
197 win_prio
= THREAD_PRIORITY_LOWEST
;
199 win_prio
= THREAD_PRIORITY_BELOW_NORMAL
;
201 win_prio
= THREAD_PRIORITY_NORMAL
;
203 win_prio
= THREAD_PRIORITY_ABOVE_NORMAL
;
204 else if (prio
<= 100)
205 win_prio
= THREAD_PRIORITY_HIGHEST
;
207 SetThreadPriority(p_internal
->thread_id
, win_prio
);
209 ResumeThread(p_internal
->thread_id
);
210 p_internal
->state
= STATE_RUNNING
;
212 return THREAD_NO_ERROR
;
215 wxThreadError
wxThread::Destroy()
217 if (p_internal
->state
!= STATE_RUNNING
)
218 return THREAD_NOT_RUNNING
;
220 if (p_internal
->defer
== FALSE
)
221 TerminateThread(p_internal
->thread_id
, 0);
223 p_internal
->state
= STATE_CANCELED
;
225 return THREAD_NO_ERROR
;
228 void wxThread::Exit(void *status
)
230 p_internal
->state
= STATE_EXITED
;
231 ExitThread((DWORD
)status
);
234 void wxThread::SetPriority(int prio
)
236 p_internal
->prio
= prio
;
239 int wxThread::GetPriority() const
241 return p_internal
->prio
;
244 void wxThread::DeferDestroy(bool on
)
246 p_internal
->defer
= on
;
249 void wxThread::TestDestroy()
251 if (p_internal
->state
== STATE_CANCELED
)
255 void *wxThread::Join()
259 if (p_internal
->state
== STATE_IDLE
)
262 if (wxThread::IsMain())
263 wxMainMutex
.Unlock();
264 WaitForSingleObject(p_internal
->thread_id
, INFINITE
);
265 if (wxThread::IsMain())
268 GetExitCodeThread(p_internal
->thread_id
, &exit_code
);
269 CloseHandle(p_internal
->thread_id
);
271 p_internal
->state
= STATE_IDLE
;
273 return (void *)exit_code
;
276 unsigned long wxThread::GetID() const
278 return (unsigned long)p_internal
->tid
;
281 bool wxThread::IsMain()
283 return (GetCurrentThread() == p_mainid
);
288 p_internal
= new wxThreadInternal();
290 p_internal
->defer
= FALSE
;
291 p_internal
->prio
= WXTHREAD_DEFAULT_PRIORITY
;
292 p_internal
->state
= STATE_IDLE
;
295 wxThread::~wxThread()
302 // The default callback just joins the thread and throws away the result.
303 void wxThread::OnExit()
308 // Automatic initialization
309 class wxThreadModule
: public wxModule
{
310 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
312 virtual bool OnInit() {
313 p_mainid
= GetCurrentThread();
319 virtual void OnExit() {
320 wxMainMutex
.Unlock();
324 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)