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
{
57 p_internal
= new wxMutexInternal
;
58 p_internal
->p_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
65 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
66 CloseHandle(p_internal
->p_mutex
);
69 wxMutexError
wxMutex::Lock()
73 ret
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
);
74 if (ret
== WAIT_ABANDONED
)
78 return MUTEX_NO_ERROR
;
81 wxMutexError
wxMutex::TryLock()
85 ret
= WaitForSingleObject(p_internal
->p_mutex
, 0);
86 if (ret
== WAIT_TIMEOUT
|| ret
== WAIT_ABANDONED
)
90 return MUTEX_NO_ERROR
;
93 wxMutexError
wxMutex::Unlock()
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
;
106 class wxConditionInternal
{
112 wxCondition::wxCondition()
114 p_internal
= new wxConditionInternal
;
115 p_internal
->event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
116 p_internal
->waiters
= 0;
119 wxCondition::~wxCondition()
121 CloseHandle(p_internal
->event
);
124 void wxCondition::Wait(wxMutex
& mutex
)
127 p_internal
->waiters
++;
128 WaitForSingleObject(p_internal
->event
, INFINITE
);
129 p_internal
->waiters
--;
133 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
,
139 p_internal
->waiters
++;
140 ret
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000));
141 p_internal
->waiters
--;
144 return (ret
!= WAIT_TIMEOUT
);
147 void wxCondition::Signal()
149 SetEvent(p_internal
->event
);
152 void wxCondition::Broadcast()
156 for (i
=0;i
<p_internal
->waiters
;i
++)
157 SetEvent(p_internal
->event
);
160 class wxThreadInternal
{
162 static DWORD
WinThreadStart(LPVOID arg
);
170 DWORD
wxThreadInternal::WinThreadStart(LPVOID arg
)
172 wxThread
*ptr
= (wxThread
*)arg
;
175 ret
= (DWORD
)ptr
->Entry();
176 ptr
->p_internal
->state
= STATE_EXITED
;
181 wxThreadError
wxThread::Create()
183 int win_prio
, prio
= p_internal
->prio
;
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
;
194 win_prio
= THREAD_PRIORITY_LOWEST
;
196 win_prio
= THREAD_PRIORITY_BELOW_NORMAL
;
198 win_prio
= THREAD_PRIORITY_NORMAL
;
200 win_prio
= THREAD_PRIORITY_ABOVE_NORMAL
;
201 else if (prio
<= 100)
202 win_prio
= THREAD_PRIORITY_HIGHEST
;
204 SetThreadPriority(p_internal
->thread_id
, win_prio
);
206 ResumeThread(p_internal
->thread_id
);
207 p_internal
->state
= STATE_RUNNING
;
209 return THREAD_NO_ERROR
;
212 wxThreadError
wxThread::Destroy()
214 if (p_internal
->state
!= STATE_RUNNING
)
215 return THREAD_NOT_RUNNING
;
217 if (p_internal
->defer
== FALSE
)
218 TerminateThread(p_internal
->thread_id
, 0);
220 p_internal
->state
= STATE_CANCELED
;
222 return THREAD_NO_ERROR
;
225 void wxThread::Exit(void *status
)
227 p_internal
->state
= STATE_EXITED
;
228 ExitThread((DWORD
)status
);
231 void wxThread::SetPriority(int prio
)
233 p_internal
->prio
= prio
;
236 int wxThread::GetPriority()
238 return p_internal
->prio
;
241 void wxThread::DeferDestroy(bool on
)
243 p_internal
->defer
= on
;
246 void wxThread::TestDestroy()
248 if (p_internal
->state
== STATE_CANCELED
)
252 void *wxThread::Join()
256 if (p_internal
->state
== STATE_IDLE
)
259 if (wxThread::IsMain())
260 wxMainMutex
.Unlock();
261 WaitForSingleObject(p_internal
->thread_id
, INFINITE
);
262 if (wxThread::IsMain())
265 GetExitCodeThread(p_internal
->thread_id
, &exit_code
);
266 CloseHandle(p_internal
->thread_id
);
268 p_internal
->state
= STATE_IDLE
;
270 return (void *)exit_code
;
273 unsigned long wxThread::GetID() const
275 return (unsigned long)p_internal
->tid
;
278 bool wxThread::IsMain() const
280 return (GetCurrentThread() == p_mainid
);
285 p_internal
= new wxThreadInternal();
287 p_internal
->defer
= FALSE
;
288 p_internal
->prio
= WXTHREAD_DEFAULT_PRIORITY
;
289 p_internal
->state
= STATE_IDLE
;
292 wxThread::~wxThread()
299 // The default callback just joins the thread and throws away the result.
300 void wxThread::OnExit()
305 // Automatic initialization
306 class wxThreadModule
: public wxModule
{
307 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
309 virtual bool OnInit() {
310 p_mainid
= GetCurrentThread();
316 virtual void OnExit() {
317 wxMainMutex
.Unlock();
321 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)