#include "wx/dynarray.h"
#include "wx/time.h"
+class MyThread;
+WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
+
// Define a new application type
class MyApp : public wxApp
{
-public:
- bool OnInit();
+ public:
+ // 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;
-WX_DEFINE_ARRAY(wxThread *, wxArrayThread);
+// Create a new application object
+IMPLEMENT_APP (MyApp)
// Define a new frame type
class MyFrame: public wxFrame
void OnIdle(wxIdleEvent &event);
- // called by dying thread _in_that_thread_context_
- void OnThreadExit(wxThread *thread);
-
private:
// helper function - creates a new thread (but doesn't run it)
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;
-
- // both of these arrays are only valid between 2 iterations of OnIdle(),
- // they're cleared each time it is excuted.
-
- // the array of threads which finished (either because they did their work
- // or because they were explicitly stopped)
- wxArrayThread m_terminated;
-
- // the array of threads which were stopped by the user and not terminated
- // by themselves - these threads shouldn't be Delete()d second time from
- // OnIdle()
- wxArrayThread m_stopped;
-
+
+
// just some place to put our messages in
wxTextCtrl *m_txtctrl;
// before doing any GUI calls we must ensure that this thread is the only
// one doing it!
- wxMutexGuiLocker guiLocker;
+
+ wxMutexGuiEnter();
+
msg << wxTime().FormatTime() << ": " << text;
m_frame->WriteText(msg);
+
+ wxMutexGuiLeave();
}
void MyThread::OnExit()
{
- m_frame->OnThreadExit(this);
+ wxCriticalSectionLocker locker(wxGetApp().m_critsect);
+
+ wxGetApp().m_threads.Remove(this);
}
void *MyThread::Entry()
EVT_IDLE(MyFrame::OnIdle)
END_EVENT_TABLE()
-// Create a new application object
-IMPLEMENT_APP (MyApp)
-
// `Main program' equivalent, creating windows and returning main app frame
bool MyApp::OnInit()
{
wxLogError("Can't create thread!");
}
- wxCriticalSectionLocker enter(m_critsect);
- m_threads.Add(thread);
+ wxCriticalSectionLocker enter(wxGetApp().m_critsect);
+ wxGetApp().m_threads.Add(thread);
return thread;
}
void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) )
{
// stop the last thread
- if ( m_threads.IsEmpty() )
+ if ( wxGetApp().m_threads.IsEmpty() )
{
wxLogError("No thread to stop!");
}
else
{
- m_critsect.Enter();
+ wxGetApp().m_critsect.Enter();
- wxThread *thread = m_threads.Last();
- m_stopped.Add(thread);
+ wxThread *thread = wxGetApp().m_threads.Last();
// 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.
- m_critsect.Leave();
+ wxGetApp().m_critsect.Leave();
thread->Delete();
void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) )
{
- wxCriticalSectionLocker enter(m_critsect);
+ wxCriticalSectionLocker enter(wxGetApp().m_critsect);
// resume first suspended thread
- size_t n = 0, count = m_threads.Count();
- while ( n < count && !m_threads[n]->IsPaused() )
+ size_t n = 0, count = wxGetApp().m_threads.Count();
+ while ( n < count && !wxGetApp().m_threads[n]->IsPaused() )
n++;
if ( n == count )
}
else
{
- m_threads[n]->Resume();
+ wxGetApp().m_threads[n]->Resume();
SetStatusText("Thread resumed.", 1);
}
void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) )
{
- wxCriticalSectionLocker enter(m_critsect);
+ wxCriticalSectionLocker enter(wxGetApp().m_critsect);
// pause last running thread
- int n = m_threads.Count() - 1;
- while ( n >= 0 && !m_threads[n]->IsRunning() )
+ int n = wxGetApp().m_threads.Count() - 1;
+ while ( n >= 0 && !wxGetApp().m_threads[n]->IsRunning() )
n--;
if ( n < 0 )
}
else
{
- m_threads[n]->Pause();
-
+ wxGetApp().m_threads[n]->Pause();
+
SetStatusText("Thread paused.", 1);
}
}
// set the frame title indicating the current number of threads
void MyFrame::OnIdle(wxIdleEvent &event)
{
- // first wait for all the threads which dies since the last call
- {
- wxCriticalSectionLocker enter(m_critsect);
-
- size_t nCount = m_terminated.GetCount();
- for ( size_t n = 0; n < nCount; n++ )
- {
- // don't delete the threads which were stopped - they were already
- // deleted in OnStopThread()
- wxThread *thread = m_terminated[n];
- if ( m_stopped.Index(thread) == wxNOT_FOUND )
- thread->Delete();
- }
-
- m_stopped.Empty();
- m_terminated.Empty();
- }
-
+ // update the counts of running/total threads
size_t nRunning = 0,
- nCount = m_threads.Count();
+ nCount = wxGetApp().m_threads.Count();
for ( size_t n = 0; n < nCount; n++ )
{
- if ( m_threads[n]->IsRunning() )
+ if ( wxGetApp().m_threads[n]->IsRunning() )
nRunning++;
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
{
- size_t count = m_threads.Count();
+ size_t count = wxGetApp().m_threads.Count();
for ( size_t i = 0; i < count; i++ )
{
- m_threads[i]->Delete();
+ wxGetApp().m_threads[0]->Delete();
}
Close(TRUE);
{
m_txtctrl->Clear();
}
-
-void MyFrame::OnThreadExit(wxThread *thread)
-{
- wxCriticalSectionLocker enter(m_critsect);
-
- m_threads.Remove(thread);
- m_terminated.Add(thread);
-}