]> git.saurik.com Git - wxWidgets.git/blame - src/palmos/thread.cpp
Allow 2-step creation of wxGenericProgressDialog.
[wxWidgets.git] / src / palmos / thread.cpp
CommitLineData
ffecfa5a
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/palmos/thread.cpp
3// Purpose: wxThread Implementation
e2731512 4// Author: William Osborne - minimal working wxPalmOS port
ffecfa5a
JS
5// Modified by:
6// Created: 10/13/04
e2731512 7// RCS-ID: $Id$
ffecfa5a
JS
8// Copyright: (c) William Osborne
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
ffecfa5a
JS
12// ----------------------------------------------------------------------------
13// headers
14// ----------------------------------------------------------------------------
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#if defined(__BORLANDC__)
20 #pragma hdrstop
21#endif
22
02761f6c
WS
23#if wxUSE_THREADS
24
25#include "wx/thread.h"
26
ffecfa5a
JS
27#ifndef WX_PRECOMP
28 #include "wx/intl.h"
29 #include "wx/app.h"
02761f6c 30 #include "wx/module.h"
ffecfa5a
JS
31#endif
32
ffecfa5a
JS
33#include "wx/apptrait.h"
34
35#include "wx/palmos/private.h"
36#include "wx/palmos/missing.h"
37
ffecfa5a
JS
38// must have this symbol defined to get _beginthread/_endthread declarations
39#ifndef _MT
40 #define _MT
41#endif
42
43#if defined(__BORLANDC__)
44 #if !defined(__MT__)
45 // I can't set -tWM in the IDE (anyone?) so have to do this
46 #define __MT__
47 #endif
48
49 #if !defined(__MFC_COMPAT__)
50 // Needed to know about _beginthreadex etc..
51 #define __MFC_COMPAT__
52 #endif
53#endif // BC++
54
55// define wxUSE_BEGIN_THREAD if the compiler has _beginthreadex() function
56// which should be used instead of Win32 ::CreateThread() if possible
57#if defined(__VISUALC__) || \
58 (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \
59 (defined(__GNUG__) && defined(__MSVCRT__)) || \
60 defined(__WATCOMC__) || defined(__MWERKS__)
61
62#ifndef __WXWINCE__
63 #undef wxUSE_BEGIN_THREAD
64 #define wxUSE_BEGIN_THREAD
65#endif
66
67#endif
68
69#ifdef wxUSE_BEGIN_THREAD
70 // the return type of the thread function entry point
71 typedef unsigned THREAD_RETVAL;
72
73 // the calling convention of the thread function entry point
74 #define THREAD_CALLCONV __stdcall
75#else
76 // the settings for CreateThread()
77 typedef DWORD THREAD_RETVAL;
78 #define THREAD_CALLCONV WINAPI
79#endif
80
81// ----------------------------------------------------------------------------
82// constants
83// ----------------------------------------------------------------------------
84
85// the possible states of the thread ("=>" shows all possible transitions from
86// this state)
87enum wxThreadState
88{
89 STATE_NEW, // didn't start execution yet (=> RUNNING)
90 STATE_RUNNING, // thread is running (=> PAUSED, CANCELED)
91 STATE_PAUSED, // thread is temporarily suspended (=> RUNNING)
92 STATE_CANCELED, // thread should terminate a.s.a.p. (=> EXITED)
93 STATE_EXITED // thread is terminating
94};
95
96// ----------------------------------------------------------------------------
97// this module globals
98// ----------------------------------------------------------------------------
99
100// TLS index of the slot where we store the pointer to the current thread
101static DWORD gs_tlsThisThread = 0xFFFFFFFF;
102
103// id of the main thread - the one which can call GUI functions without first
104// calling wxMutexGuiEnter()
105static DWORD gs_idMainThread = 0;
106
107// if it's false, some secondary thread is holding the GUI lock
108static bool gs_bGuiOwnedByMainThread = true;
109
110// critical section which controls access to all GUI functions: any secondary
111// thread (i.e. except the main one) must enter this crit section before doing
112// any GUI calls
113static wxCriticalSection *gs_critsectGui = NULL;
114
115// critical section which protects gs_nWaitingForGui variable
116static wxCriticalSection *gs_critsectWaitingForGui = NULL;
117
118// critical section which serializes WinThreadStart() and WaitForTerminate()
119// (this is a potential bottleneck, we use a single crit sect for all threads
120// in the system, but normally time spent inside it should be quite short)
121static wxCriticalSection *gs_critsectThreadDelete = NULL;
122
123// number of threads waiting for GUI in wxMutexGuiEnter()
124static size_t gs_nWaitingForGui = 0;
125
126// are we waiting for a thread termination?
127static bool gs_waitingForThread = false;
128
129// ============================================================================
130// Windows implementation of thread and related classes
131// ============================================================================
132
133// ----------------------------------------------------------------------------
134// wxCriticalSection
135// ----------------------------------------------------------------------------
136
137wxCriticalSection::wxCriticalSection()
138{
139}
140
141wxCriticalSection::~wxCriticalSection()
142{
143}
144
145void wxCriticalSection::Enter()
146{
147}
148
b9697cb4
VZ
149bool wxCriticalSection::TryEnter()
150{
151 return false;
152}
153
ffecfa5a
JS
154void wxCriticalSection::Leave()
155{
156}
157
158// ----------------------------------------------------------------------------
159// wxMutex
160// ----------------------------------------------------------------------------
161
162class wxMutexInternal
163{
164public:
165 wxMutexInternal(wxMutexType mutexType);
166 ~wxMutexInternal();
167
168 bool IsOk() const { return m_mutex != NULL; }
169
170 wxMutexError Lock() { return LockTimeout(INFINITE); }
171 wxMutexError TryLock() { return LockTimeout(0); }
172 wxMutexError Unlock();
173
174private:
175 wxMutexError LockTimeout(DWORD milliseconds);
176
177 HANDLE m_mutex;
178
c0c133e1 179 wxDECLARE_NO_COPY_CLASS(wxMutexInternal);
ffecfa5a
JS
180};
181
182// all mutexes are recursive under Win32 so we don't use mutexType
183wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType))
184{
185}
186
187wxMutexInternal::~wxMutexInternal()
188{
189}
190
191wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds)
192{
193 return wxMUTEX_NO_ERROR;
194}
195
196wxMutexError wxMutexInternal::Unlock()
197{
198 return wxMUTEX_NO_ERROR;
199}
200
201// --------------------------------------------------------------------------
202// wxSemaphore
203// --------------------------------------------------------------------------
204
205// a trivial wrapper around Win32 semaphore
206class wxSemaphoreInternal
207{
208public:
209 wxSemaphoreInternal(int initialcount, int maxcount);
210 ~wxSemaphoreInternal();
211
212 bool IsOk() const { return m_semaphore != NULL; }
213
214 wxSemaError Wait() { return WaitTimeout(INFINITE); }
215
216 wxSemaError TryWait()
217 {
218 wxSemaError rc = WaitTimeout(0);
219 if ( rc == wxSEMA_TIMEOUT )
220 rc = wxSEMA_BUSY;
221
222 return rc;
223 }
224
225 wxSemaError WaitTimeout(unsigned long milliseconds);
226
227 wxSemaError Post();
228
229private:
230 HANDLE m_semaphore;
231
c0c133e1 232 wxDECLARE_NO_COPY_CLASS(wxSemaphoreInternal);
ffecfa5a
JS
233};
234
235wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
236{
237}
238
239wxSemaphoreInternal::~wxSemaphoreInternal()
240{
241}
242
243wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds)
244{
245 return wxSEMA_NO_ERROR;
246}
247
248wxSemaError wxSemaphoreInternal::Post()
249{
250 return wxSEMA_NO_ERROR;
251}
252
253// ----------------------------------------------------------------------------
254// wxThread implementation
255// ----------------------------------------------------------------------------
256
257// wxThreadInternal class
258// ----------------------
259
260class wxThreadInternal
261{
262public:
263 wxThreadInternal(wxThread *thread)
264 {
265 m_thread = thread;
266 m_hThread = 0;
267 m_state = STATE_NEW;
268 m_priority = WXTHREAD_DEFAULT_PRIORITY;
269 m_nRef = 1;
270 }
271
272 ~wxThreadInternal()
273 {
274 Free();
275 }
276
277 void Free()
278 {
279 if ( m_hThread )
280 {
281 if ( !::CloseHandle(m_hThread) )
282 {
283 wxLogLastError(wxT("CloseHandle(thread)"));
284 }
285
286 m_hThread = 0;
287 }
288 }
289
290 // create a new (suspended) thread (for the given thread object)
291 bool Create(wxThread *thread, unsigned int stackSize);
292
293 // wait for the thread to terminate, either by itself, or by asking it
294 // (politely, this is not Kill()!) to do it
295 wxThreadError WaitForTerminate(wxCriticalSection& cs,
296 wxThread::ExitCode *pRc,
297 wxThread *threadToDelete = NULL);
298
299 // kill the thread unconditionally
300 wxThreadError Kill();
301
302 // suspend/resume/terminate
303 bool Suspend();
304 bool Resume();
305 void Cancel() { m_state = STATE_CANCELED; }
306
307 // thread state
308 void SetState(wxThreadState state) { m_state = state; }
309 wxThreadState GetState() const { return m_state; }
310
311 // thread priority
312 void SetPriority(unsigned int priority);
313 unsigned int GetPriority() const { return m_priority; }
314
315 // thread handle and id
316 HANDLE GetHandle() const { return m_hThread; }
317 DWORD GetId() const { return m_tid; }
318
319 // thread function
320 static THREAD_RETVAL THREAD_CALLCONV WinThreadStart(void *thread);
321
322 void KeepAlive()
323 {
324 if ( m_thread->IsDetached() )
325 ::InterlockedIncrement(&m_nRef);
326 }
327
328 void LetDie()
329 {
330 if ( m_thread->IsDetached() && !::InterlockedDecrement(&m_nRef) )
331 delete m_thread;
332 }
333
334private:
335 // the thread we're associated with
336 wxThread *m_thread;
337
338 HANDLE m_hThread; // handle of the thread
339 wxThreadState m_state; // state, see wxThreadState enum
340 unsigned int m_priority; // thread priority in "wx" units
341 DWORD m_tid; // thread id
342
343 // number of threads which need this thread to remain alive, when the count
344 // reaches 0 we kill the owning wxThread -- and die ourselves with it
345 LONG m_nRef;
346
c0c133e1 347 wxDECLARE_NO_COPY_CLASS(wxThreadInternal);
ffecfa5a
JS
348};
349
350// small class which keeps a thread alive during its lifetime
351class wxThreadKeepAlive
352{
353public:
354 wxThreadKeepAlive(wxThreadInternal& thrImpl) : m_thrImpl(thrImpl)
355 { m_thrImpl.KeepAlive(); }
356 ~wxThreadKeepAlive()
357 { m_thrImpl.LetDie(); }
358
359private:
360 wxThreadInternal& m_thrImpl;
361};
362
363
364THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
365{
366 THREAD_RETVAL rc;
367
368 return rc;
369}
370
371void wxThreadInternal::SetPriority(unsigned int priority)
372{
373}
374
375bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
376{
377 return false;
378}
379
380wxThreadError wxThreadInternal::Kill()
381{
382 return wxTHREAD_NO_ERROR;
383}
384
385wxThreadError
386wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
387 wxThread::ExitCode *pRc,
388 wxThread *threadToDelete)
389{
390 return wxTHREAD_NO_ERROR;
391}
392
393bool wxThreadInternal::Suspend()
394{
395 return true;
396}
397
398bool wxThreadInternal::Resume()
399{
400 return true;
401}
402
403// static functions
404// ----------------
405
406wxThread *wxThread::This()
407{
408 return NULL;
409}
410
411bool wxThread::IsMain()
412{
413 return true;
414}
415
416void wxThread::Yield()
417{
418}
419
ffecfa5a
JS
420int wxThread::GetCPUCount()
421{
422 return 1;
423}
424
425unsigned long wxThread::GetCurrentId()
426{
427 return 0;
428}
429
430bool wxThread::SetConcurrency(size_t level)
431{
432 return true;
433}
434
435// ctor and dtor
436// -------------
437
438wxThread::wxThread(wxThreadKind kind)
439{
440}
441
442wxThread::~wxThread()
443{
444}
445
446// create/start thread
447// -------------------
448
449wxThreadError wxThread::Create(unsigned int stackSize)
450{
451 return wxTHREAD_NO_ERROR;
452}
453
454wxThreadError wxThread::Run()
455{
456 return wxTHREAD_RUNNING;
457}
458
459// suspend/resume thread
460// ---------------------
461
462wxThreadError wxThread::Pause()
463{
464 return wxTHREAD_NO_ERROR;
465}
466
467wxThreadError wxThread::Resume()
468{
469 return wxTHREAD_NO_ERROR;
470}
471
472// stopping thread
473// ---------------
474
b95a7c31 475wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode))
ffecfa5a
JS
476{
477 return 0;
478}
479
b95a7c31 480wxThreadError wxThread::Delete(ExitCode *pRc, wxThreadWait WXUNUSED(waitMode))
ffecfa5a
JS
481{
482 return wxTHREAD_NO_ERROR;
483}
484
485wxThreadError wxThread::Kill()
486{
487 return wxTHREAD_NO_ERROR;
488}
489
490void wxThread::Exit(ExitCode status)
491{
492}
493
494// priority setting
495// ----------------
496
497void wxThread::SetPriority(unsigned int prio)
498{
499}
500
501unsigned int wxThread::GetPriority() const
502{
503 return 1;
504}
505
506unsigned long wxThread::GetId() const
507{
508 return 0;
509}
510
511bool wxThread::IsRunning() const
512{
513 return true;
514}
515
516bool wxThread::IsAlive() const
517{
518 return true;
519}
520
521bool wxThread::IsPaused() const
522{
523 return false;
524}
525
526bool wxThread::TestDestroy()
527{
528 return true;
529}
530
531// ----------------------------------------------------------------------------
532// Automatic initialization for thread module
533// ----------------------------------------------------------------------------
534
535class wxThreadModule : public wxModule
536{
537public:
538 virtual bool OnInit();
539 virtual void OnExit();
540
541private:
542 DECLARE_DYNAMIC_CLASS(wxThreadModule)
543};
544
545IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)
546
547bool wxThreadModule::OnInit()
548{
549 return true;
550}
551
552void wxThreadModule::OnExit()
553{
554}
555
556// ----------------------------------------------------------------------------
557// under Windows, these functions are implemented using a critical section and
558// not a mutex, so the names are a bit confusing
559// ----------------------------------------------------------------------------
560
d254213e 561void wxMutexGuiEnterImpl()
ffecfa5a
JS
562{
563}
564
d254213e 565void wxMutexGuiLeaveImpl()
ffecfa5a
JS
566{
567}
568
569void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
570{
571}
572
573bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread()
574{
575 return true;
576}
577
578// wake up the main thread if it's in ::GetMessage()
579void WXDLLIMPEXP_BASE wxWakeUpMainThread()
580{
581}
582
583bool WXDLLIMPEXP_BASE wxIsWaitingForThread()
584{
585 return false;
586}
587
588// ----------------------------------------------------------------------------
589// include common implementation code
590// ----------------------------------------------------------------------------
591
592#include "wx/thrimpl.cpp"
593
594#endif // wxUSE_THREADS