fix problems with terminating while threads are running and more (patch 781922)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23782 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -58,12 +58,10 @@ public:
|
|||||||
// crit section protects access to all of the arrays below
|
// crit section protects access to all of the arrays below
|
||||||
wxCriticalSection m_critsect;
|
wxCriticalSection m_critsect;
|
||||||
|
|
||||||
// the (mutex, condition) pair used to wait for the threads to exit, see
|
// semaphore used to wait for the threads to exit, see MyFrame::OnQuit()
|
||||||
// MyFrame::OnQuit()
|
wxSemaphore m_semAllDone;
|
||||||
wxMutex m_mutexAllDone;
|
|
||||||
wxCondition m_condAllDone;
|
|
||||||
|
|
||||||
// the last exiting thread should signal m_condAllDone if this is true
|
// the last exiting thread should post to m_semAllDone if this is true
|
||||||
// (protected by the same m_critsect)
|
// (protected by the same m_critsect)
|
||||||
bool m_waitingUntilAllDone;
|
bool m_waitingUntilAllDone;
|
||||||
};
|
};
|
||||||
@@ -212,8 +210,7 @@ void MyThread::OnExit()
|
|||||||
{
|
{
|
||||||
wxGetApp().m_waitingUntilAllDone = FALSE;
|
wxGetApp().m_waitingUntilAllDone = FALSE;
|
||||||
|
|
||||||
wxMutexLocker lock(wxGetApp().m_mutexAllDone);
|
wxGetApp().m_semAllDone.Post();
|
||||||
wxGetApp().m_condAllDone.Signal();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,19 +351,13 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
MyApp::MyApp()
|
MyApp::MyApp()
|
||||||
: m_condAllDone(m_mutexAllDone)
|
: m_semAllDone()
|
||||||
{
|
{
|
||||||
// the mutex associated with a condition must be initially locked, it will
|
|
||||||
// only be unlocked when we call Wait()
|
|
||||||
m_mutexAllDone.Lock();
|
|
||||||
|
|
||||||
m_waitingUntilAllDone = FALSE;
|
m_waitingUntilAllDone = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MyApp::~MyApp()
|
MyApp::~MyApp()
|
||||||
{
|
{
|
||||||
// the mutex must be unlocked before being destroyed
|
|
||||||
m_mutexAllDone.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `Main program' equivalent, creating windows and returning main app frame
|
// `Main program' equivalent, creating windows and returning main app frame
|
||||||
@@ -614,6 +605,8 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
|
|||||||
// we're deleting them because they will block in their OnExit() -- this is
|
// we're deleting them because they will block in their OnExit() -- this is
|
||||||
// important as otherwise we might access invalid array elements
|
// important as otherwise we might access invalid array elements
|
||||||
{
|
{
|
||||||
|
wxThread *thread;
|
||||||
|
|
||||||
wxGetApp().m_critsect.Enter();
|
wxGetApp().m_critsect.Enter();
|
||||||
|
|
||||||
// check if we have any threads running first
|
// check if we have any threads running first
|
||||||
@@ -622,27 +615,28 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
|
|||||||
|
|
||||||
if ( count )
|
if ( count )
|
||||||
{
|
{
|
||||||
// we do, ask them to stop
|
|
||||||
for ( size_t n = 0; n < count; n++ )
|
|
||||||
{
|
|
||||||
threads[n]->Delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the flag for MyThread::OnExit()
|
// set the flag for MyThread::OnExit()
|
||||||
wxGetApp().m_waitingUntilAllDone = TRUE;
|
wxGetApp().m_waitingUntilAllDone = TRUE;
|
||||||
|
|
||||||
|
// stop all threads
|
||||||
|
while ( ! threads.IsEmpty() )
|
||||||
|
{
|
||||||
|
thread = threads.Last();
|
||||||
|
|
||||||
|
wxGetApp().m_critsect.Leave();
|
||||||
|
|
||||||
|
thread->Delete();
|
||||||
|
|
||||||
|
wxGetApp().m_critsect.Enter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGetApp().m_critsect.Leave();
|
wxGetApp().m_critsect.Leave();
|
||||||
|
|
||||||
if ( count )
|
if ( count )
|
||||||
{
|
{
|
||||||
// now wait for them to really terminate but leave the GUI mutex
|
// now wait for them to really terminate
|
||||||
// before doing it as otherwise we might dead lock
|
wxGetApp().m_semAllDone.Wait();
|
||||||
wxMutexGuiLeave();
|
|
||||||
|
|
||||||
wxGetApp().m_condAllDone.Wait();
|
|
||||||
|
|
||||||
wxMutexGuiEnter();
|
|
||||||
}
|
}
|
||||||
//else: no threads to terminate, no condition to wait for
|
//else: no threads to terminate, no condition to wait for
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user