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:
@@ -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 )
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user