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