more fixes for paused thread termination

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1958 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-03-23 13:27:03 +00:00
parent d13c32e99d
commit 882eefb1f7

View File

@@ -50,15 +50,19 @@
// constants // constants
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
enum thread_state // the possible states of the thread and transitions from them
enum wxThreadState
{ {
STATE_NEW, // didn't start execution yet (=> RUNNING) STATE_NEW, // didn't start execution yet (=> RUNNING)
STATE_RUNNING, STATE_RUNNING, // running (=> PAUSED or EXITED)
STATE_PAUSED, STATE_PAUSED, // suspended (=> RUNNING or EXITED)
STATE_CANCELED, STATE_EXITED // thread doesn't exist any more
STATE_EXITED
}; };
// ----------------------------------------------------------------------------
// types
// ----------------------------------------------------------------------------
WX_DEFINE_ARRAY(wxThread *, wxArrayThread); WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -224,7 +228,7 @@ public:
// start the thread // start the thread
wxThreadError Run(); wxThreadError Run();
// ask the thread to terminate // ask the thread to terminate
void Cancel(); void Wait();
// wake up threads waiting for our termination // wake up threads waiting for our termination
void SignalExit(); void SignalExit();
// go to sleep until Resume() is called // go to sleep until Resume() is called
@@ -237,19 +241,19 @@ public:
int GetPriority() const { return m_prio; } int GetPriority() const { return m_prio; }
void SetPriority(int prio) { m_prio = prio; } void SetPriority(int prio) { m_prio = prio; }
// state // state
thread_state GetState() const { return m_state; } wxThreadState GetState() const { return m_state; }
void SetState(thread_state state) { m_state = state; } void SetState(wxThreadState state) { m_state = state; }
// id // id
pthread_t GetId() const { return thread_id; } pthread_t GetId() const { return m_threadId; }
pthread_t *GetIdPtr() { return &m_threadId; }
// "cancelled" flag // "cancelled" flag
void SetCancelFlag() { m_cancelled = TRUE; }
bool WasCancelled() const { return m_cancelled; } bool WasCancelled() const { return m_cancelled; }
//private: -- should be!
pthread_t thread_id;
private: private:
thread_state m_state; // see thread_state enum pthread_t m_threadId; // id of the thread
int m_prio; // in wxWindows units: from 0 to 100 wxThreadState m_state; // see wxThreadState enum
int m_prio; // in wxWindows units: from 0 to 100
// set when the thread should terminate // set when the thread should terminate
bool m_cancelled; bool m_cancelled;
@@ -346,17 +350,15 @@ wxThreadError wxThreadInternal::Run()
// starts executing and the mutex is still locked // starts executing and the mutex is still locked
} }
void wxThreadInternal::Cancel() void wxThreadInternal::Wait()
{ {
wxCHECK_RET( WasCancelled(), "thread should have been cancelled first" );
// if the thread we're waiting for is waiting for the GUI mutex, we will // if the thread we're waiting for is waiting for the GUI mutex, we will
// deadlock so make sure we release it temporarily // deadlock so make sure we release it temporarily
if ( wxThread::IsMain() ) if ( wxThread::IsMain() )
wxMutexGuiLeave(); wxMutexGuiLeave();
// nobody ever writes this variable so it's safe to not use any
// synchronization here
m_cancelled = TRUE;
// entering Wait() releases the mutex thus allowing SignalExit() to acquire // entering Wait() releases the mutex thus allowing SignalExit() to acquire
// it and to signal us its termination // it and to signal us its termination
m_cond.Wait(m_mutex); m_cond.Wait(m_mutex);
@@ -385,13 +387,15 @@ void wxThreadInternal::SignalExit()
void wxThreadInternal::Pause() void wxThreadInternal::Pause()
{ {
// the state is set from the thread which pauses us first, this function
// is called later so the state should have been already set
wxCHECK_RET( m_state == STATE_PAUSED, wxCHECK_RET( m_state == STATE_PAUSED,
"thread must first be paused with wxThread::Pause()." ); "thread must first be paused with wxThread::Pause()." );
// don't pause the thread which is being terminated - this would lead to // don't pause the thread which is being terminated - this would lead to
// deadlock if the thread is paused after Delete() had called Resume() but // deadlock if the thread is paused after Delete() had called Resume() but
// before it had time to call Cancel() // before it had time to call Wait()
if ( m_cancelled ) if ( WasCancelled() )
return; return;
// wait until the condition is signaled from Resume() // wait until the condition is signaled from Resume()
@@ -481,7 +485,7 @@ wxThreadError wxThread::Create()
#endif // HAVE_THREAD_PRIORITY_FUNCTIONS #endif // HAVE_THREAD_PRIORITY_FUNCTIONS
// create the new OS thread object // create the new OS thread object
int rc = pthread_create(&p_internal->thread_id, &attr, int rc = pthread_create(p_internal->GetIdPtr(), &attr,
wxThreadInternal::PthreadStart, (void *)this); wxThreadInternal::PthreadStart, (void *)this);
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
@@ -549,7 +553,7 @@ unsigned int wxThread::GetPriority() const
unsigned long wxThread::GetID() const unsigned long wxThread::GetID() const
{ {
return (unsigned long)p_internal->thread_id; return (unsigned long)p_internal->GetId();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@@ -597,9 +601,12 @@ wxThreadError wxThread::Resume()
wxThread::ExitCode wxThread::Delete() wxThread::ExitCode wxThread::Delete()
{ {
m_critsect.Enter(); m_critsect.Enter();
thread_state state = p_internal->GetState(); wxThreadState state = p_internal->GetState();
m_critsect.Leave(); m_critsect.Leave();
// ask the thread to stop
p_internal->SetCancelFlag();
switch ( state ) switch ( state )
{ {
case STATE_NEW: case STATE_NEW:
@@ -614,8 +621,8 @@ wxThread::ExitCode wxThread::Delete()
// fall through // fall through
default: default:
// set the flag telling to the thread to stop and wait // wait until the thread stops
p_internal->Cancel(); p_internal->Wait();
} }
return NULL; return NULL;
@@ -662,7 +669,7 @@ void wxThread::Exit(void *status)
// also test whether we were paused // also test whether we were paused
bool wxThread::TestDestroy() bool wxThread::TestDestroy()
{ {
wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect); wxCriticalSectionLocker lock(m_critsect);
if ( p_internal->GetState() == STATE_PAUSED ) if ( p_internal->GetState() == STATE_PAUSED )
{ {