X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/88ac883a0d005437c97a60d8195bd5e4719b1154..2bf8e4ebcc9d52bcee96e69e7013279a4f2efa37:/samples/thread/test.cpp?ds=sidebyside diff --git a/samples/thread/test.cpp b/samples/thread/test.cpp index b350260d8e..f43a48d919 100644 --- a/samples/thread/test.cpp +++ b/samples/thread/test.cpp @@ -10,11 +10,8 @@ ///////////////////////////////////////////////////////////////////////////// /* - TODO: - - 1. show how SetPriority() works. - 2. use worker threads to update progress controls instead of writing - messages - it will be more visual + TODO: use worker threads to update progress controls instead of writing + messages - it will be more visual */ #ifdef __GNUG__ @@ -41,15 +38,26 @@ #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(); + virtual 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; }; -class MyThread; -WX_DEFINE_ARRAY(wxThread *, wxArrayThread); +// Create a new application object +IMPLEMENT_APP(MyApp) // Define a new frame type class MyFrame: public wxFrame @@ -74,20 +82,10 @@ public: 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; - // just some place to put our messages in wxTextCtrl *m_txtctrl; @@ -133,7 +131,7 @@ void MyThread::WriteText(const wxString& text) wxMutexGuiEnter(); - msg << wxTime().FormatTime() << ": " << text; + msg << text; m_frame->WriteText(msg); @@ -142,14 +140,17 @@ void MyThread::WriteText(const wxString& text) void MyThread::OnExit() { - m_frame->OnThreadExit(this); + wxCriticalSectionLocker locker(wxGetApp().m_critsect); + + wxGetApp().m_threads.Remove(this); } void *MyThread::Entry() { wxString text; - text.Printf("Thread 0x%x started.\n", GetID()); + text.Printf("Thread 0x%x started (priority = %d).\n", + GetId(), GetPriority()); WriteText(text); for ( m_count = 0; m_count < 10; m_count++ ) @@ -158,14 +159,14 @@ void *MyThread::Entry() if ( TestDestroy() ) break; - text.Printf("[%u] Thread 0x%x here.\n", m_count, GetID()); + text.Printf("[%u] Thread 0x%x here.\n", m_count, GetId()); WriteText(text); // wxSleep() can't be called from non-GUI thread! wxThread::Sleep(1000); } - text.Printf("Thread 0x%x finished.\n", GetID()); + text.Printf("Thread 0x%x finished.\n", GetId()); WriteText(text); return NULL; @@ -198,9 +199,6 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) 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() { @@ -211,21 +209,21 @@ bool MyApp::OnInit() // Make a menubar wxMenu *file_menu = new wxMenu; - file_menu->Append(TEST_CLEAR, "&Clear log"); + file_menu->Append(TEST_CLEAR, "&Clear log\tCtrl-L"); file_menu->AppendSeparator(); file_menu->Append(TEST_ABOUT, "&About"); file_menu->AppendSeparator(); - file_menu->Append(TEST_QUIT, "E&xit"); + file_menu->Append(TEST_QUIT, "E&xit\tAlt-X"); wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); wxMenu *thread_menu = new wxMenu; - thread_menu->Append(TEST_START_THREAD, "&Start a new thread"); + thread_menu->Append(TEST_START_THREAD, "&Start a new thread\tCtrl-N"); thread_menu->Append(TEST_START_THREADS, "Start &many threads at once"); - thread_menu->Append(TEST_STOP_THREAD, "S&top a running thread"); + thread_menu->Append(TEST_STOP_THREAD, "S&top a running thread\tCtrl-S"); thread_menu->AppendSeparator(); - thread_menu->Append(TEST_PAUSE_THREAD, "&Pause a running thread"); - thread_menu->Append(TEST_RESUME_THREAD, "&Resume suspended thread"); + thread_menu->Append(TEST_PAUSE_THREAD, "&Pause a running thread\tCtrl-P"); + thread_menu->Append(TEST_RESUME_THREAD, "&Resume suspended thread\tCtrl-R"); menu_bar->Append(thread_menu, "&Thread"); frame->SetMenuBar(menu_bar); @@ -260,32 +258,45 @@ MyThread *MyFrame::CreateThread() 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::OnStartThreads(wxCommandEvent& WXUNUSED(event) ) { - static wxString s_str; - s_str = wxGetTextFromUser("How many threads to start: ", - "wxThread sample", - s_str, this); - if ( s_str.IsEmpty() ) - return; + static long s_num = 10; + + s_num = wxGetNumberFromUser("How many threads to start: ", "", + "wxThread sample", s_num, 1, 10000, this); + if ( s_num == -1 ) + { + s_num = 10; - size_t count, n; - sscanf(s_str, "%u", &count); - if ( count == 0 ) return; + } + + size_t count = (size_t)s_num, n; wxArrayThread threads; // first create them all... for ( n = 0; n < count; n++ ) { - threads.Add(CreateThread()); + wxThread *thr = CreateThread(); + + // we want to show the effect of SetPriority(): the first thread will + // have the lowest priority, the second - the highest, all the rest + // the normal one + if ( n == 0 ) + thr->SetPriority(WXTHREAD_MIN_PRIORITY); + else if ( n == 1 ) + thr->SetPriority(WXTHREAD_MAX_PRIORITY); + else + thr->SetPriority(WXTHREAD_DEFAULT_PRIORITY); + + threads.Add(thr); } wxString msg; @@ -314,20 +325,20 @@ void MyFrame::OnStartThread(wxCommandEvent& WXUNUSED(event) ) 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(); + 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(); @@ -337,11 +348,11 @@ void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) ) 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 ) @@ -350,7 +361,7 @@ void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) ) } else { - m_threads[n]->Resume(); + wxGetApp().m_threads[n]->Resume(); SetStatusText("Thread resumed.", 1); } @@ -358,11 +369,11 @@ void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) ) 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 ) @@ -371,7 +382,7 @@ void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) ) } else { - m_threads[n]->Pause(); + wxGetApp().m_threads[n]->Pause(); SetStatusText("Thread paused.", 1); } @@ -382,10 +393,10 @@ void MyFrame::OnIdle(wxIdleEvent &event) { // 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++; } @@ -401,10 +412,10 @@ void MyFrame::OnIdle(wxIdleEvent &event) 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); @@ -425,10 +436,3 @@ void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event)) { m_txtctrl->Clear(); } - -void MyFrame::OnThreadExit(wxThread *thread) -{ - wxCriticalSectionLocker enter(m_critsect); - - m_threads.Remove(thread); -}