]> git.saurik.com Git - wxWidgets.git/commitdiff
set a global flag on shut down instead calling Delete() on all threads sequentially...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 7 Jun 2008 16:54:29 +0000 (16:54 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 7 Jun 2008 16:54:29 +0000 (16:54 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54021 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

samples/thread/thread.cpp

index 358216c60d69626a7036a59c40f3f63d10e52a57..078442a78605ceb7c63915ed4795f19456605f2b 100644 (file)
@@ -53,20 +53,18 @@ public:
 
     virtual bool OnInit();
 
 
     virtual bool OnInit();
 
-public:
+    // critical section protects access to all of the fields below
+    wxCriticalSection m_critsect;
+
     // all the threads currently alive - as soon as the thread terminates, it's
     // removed from the array
     wxArrayThread m_threads;
 
     // 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;
-
     // semaphore used to wait for the threads to exit, see MyFrame::OnQuit()
     wxSemaphore m_semAllDone;
 
     // semaphore used to wait for the threads to exit, see MyFrame::OnQuit()
     wxSemaphore m_semAllDone;
 
-    // the last exiting thread should post to m_semAllDone if this is true
-    // (protected by the same m_critsect)
-    bool m_waitingUntilAllDone;
+    // indicates that we're shutting down and all threads should exit
+    bool m_shuttingDown;
 };
 
 // Create a new application object
 };
 
 // Create a new application object
@@ -182,16 +180,16 @@ class MyThread : public wxThread
 {
 public:
     MyThread(MyFrame *frame);
 {
 public:
     MyThread(MyFrame *frame);
+    virtual ~MyThread();
 
     // thread execution starts here
     virtual void *Entry();
 
 
     // thread execution starts here
     virtual void *Entry();
 
-    // called when the thread exits - whether it terminates normally or is
-    // stopped with Delete() (but not when it is Kill()ed!)
-    virtual void OnExit();
-
-    // write something to the text control
-    void WriteText(const wxString& text);
+    // write something to the text control in the main frame
+    void WriteText(const wxString& text)
+    {
+        m_frame->LogThreadMessage(text);
+    }
 
 public:
     unsigned m_count;
 
 public:
     unsigned m_count;
@@ -205,12 +203,7 @@ MyThread::MyThread(MyFrame *frame)
     m_frame = frame;
 }
 
     m_frame = frame;
 }
 
-void MyThread::WriteText(const wxString& text)
-{
-    m_frame->LogThreadMessage(text);
-}
-
-void MyThread::OnExit()
+MyThread::~MyThread()
 {
     wxCriticalSectionLocker locker(wxGetApp().m_critsect);
 
 {
     wxCriticalSectionLocker locker(wxGetApp().m_critsect);
 
@@ -221,9 +214,9 @@ void MyThread::OnExit()
     {
         // signal the main thread that there are no more threads left if it is
         // waiting for us
     {
         // signal the main thread that there are no more threads left if it is
         // waiting for us
-        if ( wxGetApp().m_waitingUntilAllDone )
+        if ( wxGetApp().m_shuttingDown )
         {
         {
-            wxGetApp().m_waitingUntilAllDone = false;
+            wxGetApp().m_shuttingDown = false;
 
             wxGetApp().m_semAllDone.Post();
         }
 
             wxGetApp().m_semAllDone.Post();
         }
@@ -241,7 +234,15 @@ void *MyThread::Entry()
 
     for ( m_count = 0; m_count < 10; m_count++ )
     {
 
     for ( m_count = 0; m_count < 10; m_count++ )
     {
-        // check if we were asked to exit
+        // check if the application is shutting down: in this case all threads
+        // should stop a.s.a.p.
+        {
+            wxCriticalSectionLocker locker(wxGetApp().m_critsect);
+            if ( wxGetApp().m_shuttingDown )
+                return NULL;
+        }
+
+        // check if just this thread was asked to exit
         if ( TestDestroy() )
             break;
 
         if ( TestDestroy() )
             break;
 
@@ -365,9 +366,8 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
 END_EVENT_TABLE()
 
 MyApp::MyApp()
 END_EVENT_TABLE()
 
 MyApp::MyApp()
-     : m_semAllDone()
 {
 {
-    m_waitingUntilAllDone = false;
+    m_shuttingDown = false;
 }
 
 // `Main program' equivalent, creating windows and returning main app frame
 }
 
 // `Main program' equivalent, creating windows and returning main app frame
@@ -454,40 +454,23 @@ MyFrame::~MyFrame()
     // tell all the threads to terminate: note that they can't terminate while
     // we're deleting them because they will block in their OnExit() -- this is
     // important as otherwise we might access invalid array elements
     // tell all the threads to terminate: note that they can't terminate while
     // we're deleting them because they will block in their OnExit() -- this is
     // important as otherwise we might access invalid array elements
-    wxThread *thread;
-
-    wxGetApp().m_critsect.Enter();
 
 
-    // check if we have any threads running first
-    const wxArrayThread& threads = wxGetApp().m_threads;
-    size_t count = threads.GetCount();
-
-    if ( count )
     {
     {
-        // set the flag for MyThread::OnExit()
-        wxGetApp().m_waitingUntilAllDone = true;
-
-        // stop all threads
-        while ( ! threads.IsEmpty() )
-        {
-            thread = threads.Last();
+        wxCriticalSectionLocker locker(wxGetApp().m_critsect);
 
 
-            wxGetApp().m_critsect.Leave();
+        // check if we have any threads running first
+        const wxArrayThread& threads = wxGetApp().m_threads;
+        size_t count = threads.GetCount();
 
 
-            thread->Delete();
+        if ( !count )
+            return;
 
 
-            wxGetApp().m_critsect.Enter();
-        }
+        // set the flag indicating that all threads should exit
+        wxGetApp().m_shuttingDown = true;
     }
 
     }
 
-    wxGetApp().m_critsect.Leave();
-
-    if ( count )
-    {
-        // now wait for them to really terminate
-        wxGetApp().m_semAllDone.Wait();
-    }
-    //else: no threads to terminate, no condition to wait for
+    // now wait for them to really terminate
+    wxGetApp().m_semAllDone.Wait();
 }
 
 MyThread *MyFrame::CreateThread()
 }
 
 MyThread *MyFrame::CreateThread()
@@ -569,28 +552,19 @@ void MyFrame::OnStartThread(wxCommandEvent& WXUNUSED(event) )
 
 void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) )
 {
 
 void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) )
 {
-    wxGetApp().m_critsect.Enter();
+    wxCriticalSectionLocker enter(wxGetApp().m_critsect);
 
     // stop the last thread
     if ( wxGetApp().m_threads.IsEmpty() )
     {
         wxLogError(wxT("No thread to stop!"));
 
     // stop the last thread
     if ( wxGetApp().m_threads.IsEmpty() )
     {
         wxLogError(wxT("No thread to stop!"));
-
-        wxGetApp().m_critsect.Leave();
     }
     else
     {
     }
     else
     {
-        wxThread *thread = wxGetApp().m_threads.Last();
-
-        // it's important to leave critical section before calling Delete()
-        // because delete will (implicitly) call OnExit() which also tries
-        // to enter the same crit section - would dead lock.
-        wxGetApp().m_critsect.Leave();
-
-        thread->Delete();
+        wxGetApp().m_threads.Last()->Delete();
 
 #if wxUSE_STATUSBAR
 
 #if wxUSE_STATUSBAR
-        SetStatusText(_T("Thread stopped."), 1);
+        SetStatusText(_T("Last thread stopped."), 1);
 #endif // wxUSE_STATUSBAR
     }
 }
 #endif // wxUSE_STATUSBAR
     }
 }