Better fix for thread sample code

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3494 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Guilhem Lavaux
1999-08-26 18:04:46 +00:00
parent 9baf15cea6
commit 1bd3e1efef

View File

@@ -41,15 +41,25 @@
#include "wx/dynarray.h" #include "wx/dynarray.h"
#include "wx/time.h" #include "wx/time.h"
class MyThread;
WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
// Define a new application type // Define a new application type
class MyApp : public wxApp class MyApp : public wxApp
{ {
public: public:
bool OnInit(); // all the threads currently alive - as soon as the thread terminates, it's
// removed from the array
wxArrayThread m_threads;
// crit section protects access to all of the arrays below
wxCriticalSection m_critsect;
public:
bool OnInit();
}; };
class MyThread; // Create a new application object
WX_DEFINE_ARRAY(wxThread *, wxArrayThread); IMPLEMENT_APP (MyApp)
// Define a new frame type // Define a new frame type
class MyFrame: public wxFrame class MyFrame: public wxFrame
@@ -74,19 +84,10 @@ public:
void OnIdle(wxIdleEvent &event); void OnIdle(wxIdleEvent &event);
// called by dying thread _in_that_thread_context_
void OnThreadExit(wxThread *thread);
private: private:
// helper function - creates a new thread (but doesn't run it) // helper function - creates a new thread (but doesn't run it)
MyThread *CreateThread(); MyThread *CreateThread();
// crit section protects access to all of the arrays below
wxCriticalSection m_critsect;
// all the threads currently alive - as soon as the thread terminates, it's
// removed from the array
wxArrayThread m_threads;
// just some place to put our messages in // just some place to put our messages in
wxTextCtrl *m_txtctrl; wxTextCtrl *m_txtctrl;
@@ -142,7 +143,9 @@ void MyThread::WriteText(const wxString& text)
void MyThread::OnExit() void MyThread::OnExit()
{ {
m_frame->OnThreadExit(this); wxCriticalSectionLocker locker(wxGetApp().m_critsect);
wxGetApp().m_threads.Remove(this);
} }
void *MyThread::Entry() void *MyThread::Entry()
@@ -198,9 +201,6 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_IDLE(MyFrame::OnIdle) EVT_IDLE(MyFrame::OnIdle)
END_EVENT_TABLE() END_EVENT_TABLE()
// Create a new application object
IMPLEMENT_APP (MyApp)
// `Main program' equivalent, creating windows and returning main app frame // `Main program' equivalent, creating windows and returning main app frame
bool MyApp::OnInit() bool MyApp::OnInit()
{ {
@@ -260,8 +260,8 @@ MyThread *MyFrame::CreateThread()
wxLogError("Can't create thread!"); wxLogError("Can't create thread!");
} }
wxCriticalSectionLocker enter(m_critsect); wxCriticalSectionLocker enter(wxGetApp().m_critsect);
m_threads.Add(thread); wxGetApp().m_threads.Add(thread);
return thread; return thread;
} }
@@ -314,20 +314,20 @@ void MyFrame::OnStartThread(wxCommandEvent& WXUNUSED(event) )
void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) )
{ {
// stop the last thread // stop the last thread
if ( m_threads.IsEmpty() ) if ( wxGetApp().m_threads.IsEmpty() )
{ {
wxLogError("No thread to stop!"); wxLogError("No thread to stop!");
} }
else else
{ {
m_critsect.Enter(); wxGetApp().m_critsect.Enter();
wxThread *thread = m_threads.Last(); wxThread *thread = wxGetApp().m_threads.Last();
// it's important to leave critical section before calling Delete() // it's important to leave critical section before calling Delete()
// because delete will (implicitly) call OnThreadExit() which also tries // because delete will (implicitly) call OnExit() which also tries
// to enter the same crit section - would dead lock. // to enter the same crit section - would dead lock.
m_critsect.Leave(); wxGetApp().m_critsect.Leave();
thread->Delete(); thread->Delete();
@@ -337,11 +337,11 @@ void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) )
void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) )
{ {
wxCriticalSectionLocker enter(m_critsect); wxCriticalSectionLocker enter(wxGetApp().m_critsect);
// resume first suspended thread // resume first suspended thread
size_t n = 0, count = m_threads.Count(); size_t n = 0, count = wxGetApp().m_threads.Count();
while ( n < count && !m_threads[n]->IsPaused() ) while ( n < count && !wxGetApp().m_threads[n]->IsPaused() )
n++; n++;
if ( n == count ) if ( n == count )
@@ -350,7 +350,7 @@ void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) )
} }
else else
{ {
m_threads[n]->Resume(); wxGetApp().m_threads[n]->Resume();
SetStatusText("Thread resumed.", 1); SetStatusText("Thread resumed.", 1);
} }
@@ -358,11 +358,11 @@ void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) )
void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) )
{ {
wxCriticalSectionLocker enter(m_critsect); wxCriticalSectionLocker enter(wxGetApp().m_critsect);
// pause last running thread // pause last running thread
int n = m_threads.Count() - 1; int n = wxGetApp().m_threads.Count() - 1;
while ( n >= 0 && !m_threads[n]->IsRunning() ) while ( n >= 0 && !wxGetApp().m_threads[n]->IsRunning() )
n--; n--;
if ( n < 0 ) if ( n < 0 )
@@ -371,7 +371,7 @@ void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) )
} }
else else
{ {
m_threads[n]->Pause(); wxGetApp().m_threads[n]->Pause();
SetStatusText("Thread paused.", 1); SetStatusText("Thread paused.", 1);
} }
@@ -382,10 +382,10 @@ void MyFrame::OnIdle(wxIdleEvent &event)
{ {
// update the counts of running/total threads // update the counts of running/total threads
size_t nRunning = 0, size_t nRunning = 0,
nCount = m_threads.Count(); nCount = wxGetApp().m_threads.Count();
for ( size_t n = 0; n < nCount; n++ ) for ( size_t n = 0; n < nCount; n++ )
{ {
if ( m_threads[n]->IsRunning() ) if ( wxGetApp().m_threads[n]->IsRunning() )
nRunning++; nRunning++;
} }
@@ -401,17 +401,11 @@ void MyFrame::OnIdle(wxIdleEvent &event)
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
{ {
size_t count = m_threads.Count(); size_t count = wxGetApp().m_threads.Count();
m_critsect.Enter();
for ( size_t i = 0; i < count; i++ ) for ( size_t i = 0; i < count; i++ )
{ {
wxThread *thread = m_threads[0]; wxGetApp().m_threads[0]->Delete();
m_threads.Remove(thread);
// We must always use 0 because Delete() calls OnThreadExit() and
// OnThreadExit() removes 0 from the array.
thread->Delete();
} }
m_critsect.Leave();
Close(TRUE); Close(TRUE);
} }
@@ -431,7 +425,3 @@ void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event))
{ {
m_txtctrl->Clear(); m_txtctrl->Clear();
} }
void MyFrame::OnThreadExit(wxThread *thread)
{
}