joinable and detached POSIX threads (not fully tested yet)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4769 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
7d3a036dc4
commit
9fc3ad34c5
@ -8,6 +8,25 @@ much easier to share common data between several threads, it also makes much
|
||||
easier to shoot oneself in the foot, so careful use of synchronization objects
|
||||
such as \helpref{mutexes}{wxmutex} and/or \helpref{critical sections}{wxcriticalsection} is recommended.
|
||||
|
||||
There are two types of threads in wxWindows: {\it detached} and {\it joinable}
|
||||
ones, just as in POSIX thread API (but unlike Win32 threads where all threads
|
||||
are joinable). The difference between the two is that only joinbale threads
|
||||
can return a return code - it is returned by Wait() function. The detached
|
||||
threads (default) can not be waited for.
|
||||
|
||||
You shouldn't hurry to create all the threads joinable, however, because this
|
||||
has a disadvantage as well: you {\bf must} Wait() for a joinable thread of the
|
||||
system resources used by it will never be freed and you also must delete the
|
||||
corresponding wxThread object yourself, while detached threads are of the
|
||||
"fire-and-forget" kind: you only have to start a detached thread and it will
|
||||
terminate and destroy itself.
|
||||
|
||||
This means, of course, that all detached threads {\bf must} be created on the
|
||||
heap because the thread will call {\tt delete this;} upon termination. The
|
||||
joinable threads may be created on stack (don't create global thread objects
|
||||
because they allocate memory in their constructor which is a badthing to do),
|
||||
although usually they will be created on the heap as well.
|
||||
|
||||
\wxheading{Derived from}
|
||||
|
||||
None.
|
||||
@ -84,6 +103,10 @@ created. Moreover, it must be called if \helpref{Create}{wxthreadcreate} or
|
||||
occupied by the thread object (it will be done in the destructor for joinable
|
||||
threads).
|
||||
|
||||
Delete() may be called for thread in any state: running, paused or even not yet created. Moreover,
|
||||
it must be called if \helpref{Create}{wxthreadcreate} or \helpref{Run}{wxthreadrun} fail to free
|
||||
the memory occupied by the thread object.
|
||||
|
||||
For detached threads Delete() will also delete the C++ thread object, but it
|
||||
will not do this for joinable ones.
|
||||
|
||||
|
@ -8,7 +8,10 @@ wxWindows provides a complete set of classes encapsulating objects necessary in
|
||||
multithreaded (MT) programs: the \helpref{thread}{wxthread} class itself and different
|
||||
synchronization objects: \helpref{mutexes}{wxmutex} and
|
||||
\helpref{critical sections}{wxcriticalsection} with
|
||||
\helpref{conditions}{wxcondition}.
|
||||
\helpref{conditions}{wxcondition}. The thread API in wxWindows resembles to
|
||||
POSIX1.c threads API (a.k.a. pthreads), although several functions have
|
||||
different names and some features inspired by Win32 thread API are there as
|
||||
well.
|
||||
|
||||
These classes will hopefully make writing MT programs easier and they also
|
||||
provide some extra error checking (compared to the native (be it Win32 or Posix)
|
||||
@ -21,7 +24,7 @@ new thread for each new client), but in others it might be a very poor choice
|
||||
(example: launching a separate thread when doing a long computation to show a
|
||||
progress dialog). Other implementation choices are available: for the progress
|
||||
dialog example it is far better to do the calculations in the
|
||||
\helpref{idle handler}{wxidleevent} or call \helpref{wxYield()}{wxyield}
|
||||
\helpref{idle handler}{wxidleevent} or call \helpref{wxYield()}{wxyield}
|
||||
periodically to update the screen.
|
||||
|
||||
If you do decide to use threads in your application, it is strongly recommended
|
||||
|
@ -16,13 +16,6 @@
|
||||
#pragma interface "textctrl.h"
|
||||
#endif
|
||||
|
||||
// can we use RICHEDIT class for wxTextCtrl implementation?
|
||||
#if defined(__WIN95__) && !defined(__TWIN32__) && !defined(__WXWINE__)
|
||||
#define wxUSE_RICHEDIT 1
|
||||
#else
|
||||
#define wxUSE_RICHEDIT 0
|
||||
#endif
|
||||
|
||||
class WXDLLEXPORT wxTextCtrl : public wxTextCtrlBase
|
||||
{
|
||||
public:
|
||||
|
@ -40,21 +40,21 @@
|
||||
|
||||
enum wxMutexError
|
||||
{
|
||||
wxMUTEX_NO_ERROR = 0,
|
||||
wxMUTEX_DEAD_LOCK, // Mutex has been already locked by THE CALLING thread
|
||||
wxMUTEX_BUSY, // Mutex has been already locked by ONE thread
|
||||
wxMUTEX_UNLOCKED,
|
||||
wxMUTEX_MISC_ERROR
|
||||
wxMUTEX_NO_ERROR = 0,
|
||||
wxMUTEX_DEAD_LOCK, // Mutex has been already locked by THE CALLING thread
|
||||
wxMUTEX_BUSY, // Mutex has been already locked by ONE thread
|
||||
wxMUTEX_UNLOCKED,
|
||||
wxMUTEX_MISC_ERROR
|
||||
};
|
||||
|
||||
enum wxThreadError
|
||||
{
|
||||
wxTHREAD_NO_ERROR = 0, // No error
|
||||
wxTHREAD_NO_RESOURCE, // No resource left to create a new thread
|
||||
wxTHREAD_RUNNING, // The thread is already running
|
||||
wxTHREAD_NOT_RUNNING, // The thread isn't running
|
||||
wxTHREAD_KILLED, // Thread we waited for had to be killed
|
||||
wxTHREAD_MISC_ERROR // Some other error
|
||||
wxTHREAD_NO_ERROR = 0, // No error
|
||||
wxTHREAD_NO_RESOURCE, // No resource left to create a new thread
|
||||
wxTHREAD_RUNNING, // The thread is already running
|
||||
wxTHREAD_NOT_RUNNING, // The thread isn't running
|
||||
wxTHREAD_KILLED, // Thread we waited for had to be killed
|
||||
wxTHREAD_MISC_ERROR // Some other error
|
||||
};
|
||||
|
||||
enum wxThreadKind
|
||||
@ -106,7 +106,7 @@ protected:
|
||||
wxMutex& operator=(const wxMutex&);
|
||||
|
||||
int m_locked;
|
||||
wxMutexInternal *p_internal;
|
||||
wxMutexInternal *m_internal;
|
||||
};
|
||||
|
||||
// a helper class which locks the mutex in the ctor and unlocks it in the dtor:
|
||||
@ -213,28 +213,32 @@ private:
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Condition handler.
|
||||
// Condition variable: allows to block the thread execution until something
|
||||
// happens (== condition is signaled)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class wxConditionInternal;
|
||||
class WXDLLEXPORT wxCondition
|
||||
{
|
||||
public:
|
||||
// constructor & destructor
|
||||
wxCondition();
|
||||
~wxCondition();
|
||||
// constructor & destructor
|
||||
wxCondition();
|
||||
~wxCondition();
|
||||
|
||||
// Waits indefinitely.
|
||||
void Wait(wxMutex& mutex);
|
||||
// Waits until a signal is raised or the timeout is elapsed.
|
||||
bool Wait(wxMutex& mutex, unsigned long sec, unsigned long nsec);
|
||||
// Raises a signal: only one "Waiter" is released.
|
||||
void Signal();
|
||||
// Broadcasts to all "Waiters".
|
||||
void Broadcast();
|
||||
// wait until the condition is signaled
|
||||
// waits indefinitely.
|
||||
void Wait();
|
||||
// waits until a signal is raised or the timeout elapses
|
||||
bool Wait(unsigned long sec, unsigned long nsec);
|
||||
|
||||
// signal the condition
|
||||
// wakes up one (and only one) of the waiting threads
|
||||
void Signal();
|
||||
// wakes up all threads waiting onthis condition
|
||||
void Broadcast();
|
||||
|
||||
private:
|
||||
wxConditionInternal *p_internal;
|
||||
wxConditionInternal *m_internal;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -381,7 +385,7 @@ private:
|
||||
friend class wxThreadInternal;
|
||||
|
||||
// the (platform-dependent) thread class implementation
|
||||
wxThreadInternal *p_internal;
|
||||
wxThreadInternal *m_internal;
|
||||
|
||||
// protects access to any methods of wxThreadInternal object
|
||||
wxCriticalSection m_critsect;
|
||||
|
@ -31,9 +31,10 @@
|
||||
|
||||
//#define TEST_ARRAYS
|
||||
//#define TEST_LOG
|
||||
//#define TEST_THREADS
|
||||
//#define TEST_STRINGS
|
||||
#define TEST_THREADS
|
||||
//#define TEST_TIME
|
||||
#define TEST_LONGLONG
|
||||
//#define TEST_LONGLONG
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
@ -52,7 +53,7 @@ static void TestSpeed()
|
||||
{
|
||||
static const long max = 100000000;
|
||||
long n;
|
||||
|
||||
|
||||
{
|
||||
wxStopWatch sw;
|
||||
|
||||
@ -151,7 +152,7 @@ wxThread::ExitCode MyJoinableThread::Entry()
|
||||
class MyDetachedThread : public wxThread
|
||||
{
|
||||
public:
|
||||
MyDetachedThread(char ch) { m_ch = ch; Create(); }
|
||||
MyDetachedThread(size_t n, char ch) { m_n = n; m_ch = ch; Create(); }
|
||||
|
||||
// thread execution starts here
|
||||
virtual ExitCode Entry();
|
||||
@ -160,7 +161,8 @@ public:
|
||||
virtual void OnExit();
|
||||
|
||||
private:
|
||||
char m_ch;
|
||||
size_t m_n; // number of characters to write
|
||||
char m_ch; // character to write
|
||||
};
|
||||
|
||||
wxThread::ExitCode MyDetachedThread::Entry()
|
||||
@ -173,8 +175,7 @@ wxThread::ExitCode MyDetachedThread::Entry()
|
||||
gs_counter++;
|
||||
}
|
||||
|
||||
static const size_t nIter = 10;
|
||||
for ( size_t n = 0; n < nIter; n++ )
|
||||
for ( size_t n = 0; n < m_n; n++ )
|
||||
{
|
||||
if ( TestDestroy() )
|
||||
break;
|
||||
@ -190,11 +191,86 @@ wxThread::ExitCode MyDetachedThread::Entry()
|
||||
|
||||
void MyDetachedThread::OnExit()
|
||||
{
|
||||
wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
|
||||
|
||||
wxCriticalSectionLocker lock(gs_critsect);
|
||||
if ( !--gs_counter )
|
||||
gs_cond.Signal();
|
||||
}
|
||||
|
||||
void TestDetachedThreads()
|
||||
{
|
||||
puts("*** Testing detached threads ***");
|
||||
|
||||
static const size_t nThreads = 3;
|
||||
MyDetachedThread *threads[nThreads];
|
||||
size_t n;
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
{
|
||||
threads[n] = new MyDetachedThread(10, 'A' + n);
|
||||
}
|
||||
|
||||
threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
|
||||
threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
|
||||
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
{
|
||||
threads[n]->Run();
|
||||
}
|
||||
|
||||
// wait until all threads terminate
|
||||
gs_cond.Wait();
|
||||
|
||||
puts("");
|
||||
}
|
||||
|
||||
void TestJoinableThreads()
|
||||
{
|
||||
puts("*** Testing a joinable thread (a loooong calculation...) ***");
|
||||
|
||||
// calc 10! in the background
|
||||
MyJoinableThread thread(10);
|
||||
thread.Run();
|
||||
|
||||
printf("\nThread terminated with exit code %lu.\n",
|
||||
(unsigned long)thread.Wait());
|
||||
}
|
||||
|
||||
void TestThreadSuspend()
|
||||
{
|
||||
MyDetachedThread *thread = new MyDetachedThread(30, 'X');
|
||||
|
||||
thread->Run();
|
||||
|
||||
// this is for this demo only, in a real life program we'd use another
|
||||
// condition variable which would be signaled from wxThread::Entry() to
|
||||
// tell us that the thread really started running - but here just wait a
|
||||
// bit and hope that it will be enough (the problem is, of course, that
|
||||
// the thread might still not run when we call Pause() which will result
|
||||
// in an error)
|
||||
wxThread::Sleep(300);
|
||||
|
||||
for ( size_t n = 0; n < 3; n++ )
|
||||
{
|
||||
thread->Pause();
|
||||
|
||||
puts("\nThread suspended");
|
||||
if ( n > 0 )
|
||||
{
|
||||
// don't sleep but resume immediately the first time
|
||||
wxThread::Sleep(300);
|
||||
}
|
||||
puts("Going to resume the thread");
|
||||
|
||||
thread->Resume();
|
||||
}
|
||||
|
||||
// wait until the thread terminates
|
||||
gs_cond.Wait();
|
||||
|
||||
puts("");
|
||||
}
|
||||
|
||||
#endif // TEST_THREADS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -216,6 +292,64 @@ void PrintArray(const char* name, const wxArrayString& array)
|
||||
|
||||
#endif // TEST_ARRAYS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// strings
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef TEST_STRINGS
|
||||
|
||||
#include "wx/timer.h"
|
||||
|
||||
void TestString()
|
||||
{
|
||||
wxStopWatch sw;
|
||||
|
||||
wxString a, b, c;
|
||||
|
||||
a.reserve (128);
|
||||
b.reserve (128);
|
||||
c.reserve (128);
|
||||
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
{
|
||||
a = "Hello";
|
||||
b = " world";
|
||||
c = "! How'ya doin'?";
|
||||
a += b;
|
||||
a += c;
|
||||
c = "Hello world! What's up?";
|
||||
if (c != a)
|
||||
c = "Doh!";
|
||||
}
|
||||
|
||||
printf ("TestString elapsed time: %ld\n", sw.Time());
|
||||
}
|
||||
|
||||
void TestPChar()
|
||||
{
|
||||
wxStopWatch sw;
|
||||
|
||||
char a [128];
|
||||
char b [128];
|
||||
char c [128];
|
||||
|
||||
for (int i = 0; i < 1000000; ++i)
|
||||
{
|
||||
strcpy (a, "Hello");
|
||||
strcpy (b, " world");
|
||||
strcpy (c, "! How'ya doin'?");
|
||||
strcat (a, b);
|
||||
strcat (a, c);
|
||||
strcpy (c, "Hello world! What's up?");
|
||||
if (strcmp (c, a) == 0)
|
||||
strcpy (c, "Doh!");
|
||||
}
|
||||
|
||||
printf ("TestPChar elapsed time: %ld\n", sw.Time());
|
||||
}
|
||||
|
||||
#endif // TEST_STRINGS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// entry point
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -227,6 +361,11 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
|
||||
}
|
||||
|
||||
#ifdef TEST_STRINGS
|
||||
TestPChar();
|
||||
TestString();
|
||||
#endif // TEST_STRINGS
|
||||
|
||||
#ifdef TEST_ARRAYS
|
||||
wxArrayString a1;
|
||||
a1.Add("tiger");
|
||||
@ -279,38 +418,15 @@ int main(int argc, char **argv)
|
||||
#endif // TEST_LOG
|
||||
|
||||
#ifdef TEST_THREADS
|
||||
puts("Testing detached threads...");
|
||||
if ( argc > 1 && argv[1][0] == 't' )
|
||||
wxLog::AddTraceMask("thread");
|
||||
|
||||
static const size_t nThreads = 3;
|
||||
MyDetachedThread *threads[nThreads];
|
||||
size_t n;
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
TestThreadSuspend();
|
||||
if ( 0 )
|
||||
{
|
||||
threads[n] = new MyDetachedThread('A' + n);
|
||||
TestDetachedThreads();
|
||||
TestJoinableThreads();
|
||||
}
|
||||
|
||||
threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
|
||||
threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
|
||||
|
||||
for ( n = 0; n < nThreads; n++ )
|
||||
{
|
||||
threads[n]->Run();
|
||||
}
|
||||
|
||||
// wait until all threads terminate
|
||||
wxMutex mutex;
|
||||
mutex.Lock();
|
||||
gs_cond.Wait(mutex);
|
||||
mutex.Unlock();
|
||||
|
||||
puts("\n\nTesting a joinable thread used for a loooong calculation...");
|
||||
|
||||
// calc 10! in the background
|
||||
MyJoinableThread thread(10);
|
||||
thread.Run();
|
||||
|
||||
printf("\nThread terminated with exit code %lu.\n",
|
||||
(unsigned long)thread.Wait());
|
||||
#endif // TEST_THREADS
|
||||
|
||||
#ifdef TEST_LONGLONG
|
||||
|
@ -104,9 +104,9 @@ public:
|
||||
|
||||
wxMutex::wxMutex()
|
||||
{
|
||||
p_internal = new wxMutexInternal;
|
||||
p_internal->p_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
if ( !p_internal->p_mutex )
|
||||
m_internal = new wxMutexInternal;
|
||||
m_internal->p_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
if ( !m_internal->p_mutex )
|
||||
{
|
||||
wxLogSysError(_("Can not create mutex."));
|
||||
}
|
||||
@ -118,14 +118,14 @@ wxMutex::~wxMutex()
|
||||
{
|
||||
if (m_locked > 0)
|
||||
wxLogDebug(wxT("Warning: freeing a locked mutex (%d locks)."), m_locked);
|
||||
CloseHandle(p_internal->p_mutex);
|
||||
CloseHandle(m_internal->p_mutex);
|
||||
}
|
||||
|
||||
wxMutexError wxMutex::Lock()
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
ret = WaitForSingleObject(p_internal->p_mutex, INFINITE);
|
||||
ret = WaitForSingleObject(m_internal->p_mutex, INFINITE);
|
||||
switch ( ret )
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
@ -152,7 +152,7 @@ wxMutexError wxMutex::TryLock()
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
ret = WaitForSingleObject(p_internal->p_mutex, 0);
|
||||
ret = WaitForSingleObject(m_internal->p_mutex, 0);
|
||||
if (ret == WAIT_TIMEOUT || ret == WAIT_ABANDONED)
|
||||
return wxMUTEX_BUSY;
|
||||
|
||||
@ -165,7 +165,7 @@ wxMutexError wxMutex::Unlock()
|
||||
if (m_locked > 0)
|
||||
m_locked--;
|
||||
|
||||
BOOL ret = ReleaseMutex(p_internal->p_mutex);
|
||||
BOOL ret = ReleaseMutex(m_internal->p_mutex);
|
||||
if ( ret == 0 )
|
||||
{
|
||||
wxLogSysError(_("Couldn't release a mutex"));
|
||||
@ -197,16 +197,14 @@ public:
|
||||
waiters = 0;
|
||||
}
|
||||
|
||||
bool Wait(wxMutex& mutex, DWORD timeout)
|
||||
bool Wait(DWORD timeout)
|
||||
{
|
||||
mutex.Unlock();
|
||||
waiters++;
|
||||
|
||||
// FIXME this should be MsgWaitForMultipleObjects() as well probably
|
||||
DWORD rc = ::WaitForSingleObject(event, timeout);
|
||||
|
||||
waiters--;
|
||||
mutex.Lock();
|
||||
|
||||
return rc != WAIT_TIMEOUT;
|
||||
}
|
||||
@ -228,24 +226,23 @@ public:
|
||||
|
||||
wxCondition::wxCondition()
|
||||
{
|
||||
p_internal = new wxConditionInternal;
|
||||
m_internal = new wxConditionInternal;
|
||||
}
|
||||
|
||||
wxCondition::~wxCondition()
|
||||
{
|
||||
delete p_internal;
|
||||
delete m_internal;
|
||||
}
|
||||
|
||||
void wxCondition::Wait(wxMutex& mutex)
|
||||
void wxCondition::Wait()
|
||||
{
|
||||
(void)p_internal->Wait(mutex, INFINITE);
|
||||
(void)m_internal->Wait(INFINITE);
|
||||
}
|
||||
|
||||
bool wxCondition::Wait(wxMutex& mutex,
|
||||
unsigned long sec,
|
||||
bool wxCondition::Wait(unsigned long sec,
|
||||
unsigned long nsec)
|
||||
{
|
||||
return p_internal->Wait(mutex, sec*1000 + nsec/1000000);
|
||||
return m_internal->Wait(sec*1000 + nsec/1000000);
|
||||
}
|
||||
|
||||
void wxCondition::Signal()
|
||||
@ -255,7 +252,7 @@ void wxCondition::Signal()
|
||||
// someone waits on it. In any case, the system will return it to a non
|
||||
// signalled state afterwards. If multiple threads are waiting, only one
|
||||
// will be woken up.
|
||||
if ( !::SetEvent(p_internal->event) )
|
||||
if ( !::SetEvent(m_internal->event) )
|
||||
{
|
||||
wxLogLastError("SetEvent");
|
||||
}
|
||||
@ -266,7 +263,7 @@ void wxCondition::Broadcast()
|
||||
// this works because all these threads are already waiting and so each
|
||||
// SetEvent() inside Signal() is really a PulseEvent() because the event
|
||||
// state is immediately returned to non-signaled
|
||||
for ( int i = 0; i < p_internal->waiters; i++ )
|
||||
for ( int i = 0; i < m_internal->waiters; i++ )
|
||||
{
|
||||
Signal();
|
||||
}
|
||||
@ -378,8 +375,8 @@ DWORD wxThreadInternal::WinThreadStart(wxThread *thread)
|
||||
|
||||
// enter m_critsect before changing the thread state
|
||||
thread->m_critsect.Enter();
|
||||
bool wasCancelled = thread->p_internal->GetState() == STATE_CANCELED;
|
||||
thread->p_internal->SetState(STATE_EXITED);
|
||||
bool wasCancelled = thread->m_internal->GetState() == STATE_CANCELED;
|
||||
thread->m_internal->SetState(STATE_EXITED);
|
||||
thread->m_critsect.Leave();
|
||||
|
||||
thread->OnExit();
|
||||
@ -535,14 +532,14 @@ void wxThread::Sleep(unsigned long milliseconds)
|
||||
|
||||
wxThread::wxThread(wxThreadKind kind)
|
||||
{
|
||||
p_internal = new wxThreadInternal();
|
||||
m_internal = new wxThreadInternal();
|
||||
|
||||
m_isDetached = kind == wxTHREAD_DETACHED;
|
||||
}
|
||||
|
||||
wxThread::~wxThread()
|
||||
{
|
||||
delete p_internal;
|
||||
delete m_internal;
|
||||
}
|
||||
|
||||
// create/start thread
|
||||
@ -552,7 +549,7 @@ wxThreadError wxThread::Create()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
if ( !p_internal->Create(this) )
|
||||
if ( !m_internal->Create(this) )
|
||||
return wxTHREAD_NO_RESOURCE;
|
||||
|
||||
return wxTHREAD_NO_ERROR;
|
||||
@ -562,7 +559,7 @@ wxThreadError wxThread::Run()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
if ( p_internal->GetState() != STATE_NEW )
|
||||
if ( m_internal->GetState() != STATE_NEW )
|
||||
{
|
||||
// actually, it may be almost any state at all, not only STATE_RUNNING
|
||||
return wxTHREAD_RUNNING;
|
||||
@ -579,14 +576,14 @@ wxThreadError wxThread::Pause()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
return p_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
|
||||
return m_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
|
||||
}
|
||||
|
||||
wxThreadError wxThread::Resume()
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
return p_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
|
||||
return m_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
|
||||
}
|
||||
|
||||
// stopping thread
|
||||
@ -603,7 +600,7 @@ wxThread::ExitCode wxThread::Wait()
|
||||
|
||||
(void)Delete(&rc);
|
||||
|
||||
p_internal->Free();
|
||||
m_internal->Free();
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -616,7 +613,7 @@ wxThreadError wxThread::Delete(ExitCode *pRc)
|
||||
if ( IsPaused() )
|
||||
Resume();
|
||||
|
||||
HANDLE hThread = p_internal->GetHandle();
|
||||
HANDLE hThread = m_internal->GetHandle();
|
||||
|
||||
if ( IsRunning() )
|
||||
{
|
||||
@ -634,7 +631,7 @@ wxThreadError wxThread::Delete(ExitCode *pRc)
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
p_internal->Cancel();
|
||||
m_internal->Cancel();
|
||||
}
|
||||
|
||||
#if wxUSE_GUI
|
||||
@ -742,14 +739,14 @@ wxThreadError wxThread::Kill()
|
||||
if ( !IsRunning() )
|
||||
return wxTHREAD_NOT_RUNNING;
|
||||
|
||||
if ( !::TerminateThread(p_internal->GetHandle(), (DWORD)-1) )
|
||||
if ( !::TerminateThread(m_internal->GetHandle(), (DWORD)-1) )
|
||||
{
|
||||
wxLogSysError(_("Couldn't terminate thread"));
|
||||
|
||||
return wxTHREAD_MISC_ERROR;
|
||||
}
|
||||
|
||||
p_internal->Free();
|
||||
m_internal->Free();
|
||||
|
||||
if ( IsDetached() )
|
||||
{
|
||||
@ -761,7 +758,7 @@ wxThreadError wxThread::Kill()
|
||||
|
||||
void wxThread::Exit(ExitCode status)
|
||||
{
|
||||
p_internal->Free();
|
||||
m_internal->Free();
|
||||
|
||||
if ( IsDetached() )
|
||||
{
|
||||
@ -784,50 +781,50 @@ void wxThread::SetPriority(unsigned int prio)
|
||||
{
|
||||
wxCriticalSectionLocker lock(m_critsect);
|
||||
|
||||
p_internal->SetPriority(prio);
|
||||
m_internal->SetPriority(prio);
|
||||
}
|
||||
|
||||
unsigned int wxThread::GetPriority() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetPriority();
|
||||
return m_internal->GetPriority();
|
||||
}
|
||||
|
||||
unsigned long wxThread::GetId() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return (unsigned long)p_internal->GetId();
|
||||
return (unsigned long)m_internal->GetId();
|
||||
}
|
||||
|
||||
bool wxThread::IsRunning() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetState() == STATE_RUNNING;
|
||||
return m_internal->GetState() == STATE_RUNNING;
|
||||
}
|
||||
|
||||
bool wxThread::IsAlive() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return (p_internal->GetState() == STATE_RUNNING) ||
|
||||
(p_internal->GetState() == STATE_PAUSED);
|
||||
return (m_internal->GetState() == STATE_RUNNING) ||
|
||||
(m_internal->GetState() == STATE_PAUSED);
|
||||
}
|
||||
|
||||
bool wxThread::IsPaused() const
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetState() == STATE_PAUSED;
|
||||
return m_internal->GetState() == STATE_PAUSED;
|
||||
}
|
||||
|
||||
bool wxThread::TestDestroy()
|
||||
{
|
||||
wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
|
||||
|
||||
return p_internal->GetState() == STATE_CANCELED;
|
||||
return m_internal->GetState() == STATE_CANCELED;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user