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 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
19 #if defined(__BORLANDC__)
30 #include "wx/module.h"
31 #include "wx/thread.h"
40 /////////////////////////////////////////////////////////////////////////////
42 /////////////////////////////////////////////////////////////////////////////
44 static HANDLE p_mainid
;
45 wxMutex wxMainMutex
; // controls access to all GUI functions
47 /////////////////////////////////////////////////////////////////////////////
48 // Windows implementation
49 /////////////////////////////////////////////////////////////////////////////
51 class wxMutexInternal
{
58 p_internal
= new wxMutexInternal
;
59 p_internal
->p_mutex
= CreateMutex(NULL
, FALSE
, NULL
);
66 wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked
);
67 CloseHandle(p_internal
->p_mutex
);
70 wxMutexError
wxMutex::Lock()
74 ret
= WaitForSingleObject(p_internal
->p_mutex
, INFINITE
);
75 if (ret
== WAIT_ABANDONED
)
79 return MUTEX_NO_ERROR
;
82 wxMutexError
wxMutex::TryLock()
86 ret
= WaitForSingleObject(p_internal
->p_mutex
, 0);
87 if (ret
== WAIT_TIMEOUT
|| ret
== WAIT_ABANDONED
)
91 return MUTEX_NO_ERROR
;
94 wxMutexError
wxMutex::Unlock()
101 // Why does this have 3 args? The redundant ones removed by JACS
102 // ret = ReleaseMutex(p_internal->p_mutex, 1, NULL);
103 ret
= ReleaseMutex(p_internal
->p_mutex
);
104 return MUTEX_NO_ERROR
;
107 class wxConditionInternal
{
113 wxCondition::wxCondition()
115 p_internal
= new wxConditionInternal
;
116 p_internal
->event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
117 p_internal
->waiters
= 0;
120 wxCondition::~wxCondition()
122 CloseHandle(p_internal
->event
);
125 void wxCondition::Wait(wxMutex
& mutex
)
128 p_internal
->waiters
++;
129 WaitForSingleObject(p_internal
->event
, INFINITE
);
130 p_internal
->waiters
--;
134 bool wxCondition::Wait(wxMutex
& mutex
, unsigned long sec
,
140 p_internal
->waiters
++;
141 ret
= WaitForSingleObject(p_internal
->event
, (sec
*1000)+(nsec
/1000000));
142 p_internal
->waiters
--;
145 return (ret
!= WAIT_TIMEOUT
);
148 void wxCondition::Signal()
150 SetEvent(p_internal
->event
);
153 void wxCondition::Broadcast()
157 for (i
=0;i
<p_internal
->waiters
;i
++)
158 SetEvent(p_internal
->event
);
161 class wxThreadInternal
{
163 static DWORD
WinThreadStart(LPVOID arg
);
171 DWORD
wxThreadInternal::WinThreadStart(LPVOID arg
)
173 wxThread
*ptr
= (wxThread
*)arg
;
176 ret
= (DWORD
)ptr
->Entry();
177 ptr
->p_internal
->state
= STATE_EXITED
;
182 wxThreadError
wxThread::Create()
184 int win_prio
, prio
= p_internal
->prio
;
186 p_internal
->thread_id
= CreateThread(NULL
, 0,
187 (LPTHREAD_START_ROUTINE
)wxThreadInternal::WinThreadStart
,
188 (void *)this, CREATE_SUSPENDED
, &p_internal
->tid
);
189 if (p_internal
->thread_id
== NULL
) {
190 printf("Error = %d\n", GetLastError());
191 return THREAD_NO_RESOURCE
;
195 win_prio
= THREAD_PRIORITY_LOWEST
;
197 win_prio
= THREAD_PRIORITY_BELOW_NORMAL
;
199 win_prio
= THREAD_PRIORITY_NORMAL
;
201 win_prio
= THREAD_PRIORITY_ABOVE_NORMAL
;
202 else if (prio
<= 100)
203 win_prio
= THREAD_PRIORITY_HIGHEST
;
205 SetThreadPriority(p_internal
->thread_id
, win_prio
);
207 ResumeThread(p_internal
->thread_id
);
208 p_internal
->state
= STATE_RUNNING
;
210 return THREAD_NO_ERROR
;
213 wxThreadError
wxThread::Destroy()
215 if (p_internal
->state
!= STATE_RUNNING
)
216 return THREAD_NOT_RUNNING
;
218 if (p_internal
->defer
== FALSE
)
219 TerminateThread(p_internal
->thread_id
, 0);
221 p_internal
->state
= STATE_CANCELED
;
223 return THREAD_NO_ERROR
;
226 void wxThread::Exit(void *status
)
228 p_internal
->state
= STATE_EXITED
;
229 ExitThread((DWORD
)status
);
232 void wxThread::SetPriority(int prio
)
234 p_internal
->prio
= prio
;
237 int wxThread::GetPriority() const
239 return p_internal
->prio
;
242 void wxThread::DeferDestroy(bool on
)
244 p_internal
->defer
= on
;
247 void wxThread::TestDestroy()
249 if (p_internal
->state
== STATE_CANCELED
)
253 void *wxThread::Join()
257 if (p_internal
->state
== STATE_IDLE
)
260 if (wxThread::IsMain())
261 wxMainMutex
.Unlock();
262 WaitForSingleObject(p_internal
->thread_id
, INFINITE
);
263 if (wxThread::IsMain())
266 GetExitCodeThread(p_internal
->thread_id
, &exit_code
);
267 CloseHandle(p_internal
->thread_id
);
269 p_internal
->state
= STATE_IDLE
;
271 return (void *)exit_code
;
274 unsigned long wxThread::GetID() const
276 return (unsigned long)p_internal
->tid
;
279 bool wxThread::IsMain()
281 return (GetCurrentThread() == p_mainid
);
286 p_internal
= new wxThreadInternal();
288 p_internal
->defer
= FALSE
;
289 p_internal
->prio
= WXTHREAD_DEFAULT_PRIORITY
;
290 p_internal
->state
= STATE_IDLE
;
293 wxThread::~wxThread()
300 // The default callback just joins the thread and throws away the result.
301 void wxThread::OnExit()
306 // Automatic initialization
307 class wxThreadModule
: public wxModule
{
308 DECLARE_DYNAMIC_CLASS(wxThreadModule
)
310 virtual bool OnInit() {
311 p_mainid
= GetCurrentThread();
317 virtual void OnExit() {
318 wxMainMutex
.Unlock();
322 IMPLEMENT_DYNAMIC_CLASS(wxThreadModule
, wxModule
)