X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/123a7fddb89d0d39f8c280aea95182d054c8887b..06cfab17389f4bbd38560dd86ee39931e979bb1e:/samples/thread/test.cpp diff --git a/samples/thread/test.cpp b/samples/thread/test.cpp index 47149b62a7..a2aaaf940c 100644 --- a/samples/thread/test.cpp +++ b/samples/thread/test.cpp @@ -6,7 +6,7 @@ // Created: 06/16/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart, Markus Holzem, Guilhem Lavaux -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ @@ -18,186 +18,284 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #ifndef WX_PRECOMP -#include "wx/wx.h" + #include "wx/wx.h" #endif +#if !wxUSE_THREADS + #error "This sample requires thread support!" +#endif // wxUSE_THREADS + #include "wx/thread.h" #include "wx/dynarray.h" +#include "wx/time.h" // Define a new application type class MyApp: public wxApp { - public: +public: bool OnInit(void); }; -wxMutex text_mutex; - -WX_DEFINE_ARRAY(wxThread *,wxArrayThread); +WX_DEFINE_ARRAY(wxThread *, wxArrayThread); // Define a new frame type class MyFrame: public wxFrame { - public: +public: + // ctor MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h); - - public: + + // operations + void WriteText(const wxString& text) { m_txtctrl->WriteText(text); } + + // callbacks void OnQuit(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); + void OnStartThread(wxCommandEvent& event); void OnStopThread(wxCommandEvent& event); void OnPauseThread(wxCommandEvent& event); - bool OnClose(void) { return TRUE; } + void OnResumeThread(wxCommandEvent& event); + + void OnSize(wxSizeEvent &event); + void OnIdle(wxIdleEvent &event); + bool OnClose() { return TRUE; } - public: - wxArrayThread m_threads; - wxTextCtrl *m_txtctrl; +public: + wxArrayThread m_threads; - DECLARE_EVENT_TABLE() +private: + wxTextCtrl *m_txtctrl; + + DECLARE_EVENT_TABLE() }; class MyThread: public wxThread { - public: +public: MyThread(MyFrame *frame); - void *Entry(); - public: + // thread execution starts here + virtual void *Entry(); + + // write something to the text control + void WriteText(const wxString& text); + +public: + size_t m_count; MyFrame *m_frame; }; MyThread::MyThread(MyFrame *frame) - : wxThread() + : wxThread() +{ + m_count = 0; + m_frame = frame; +} + +void MyThread::WriteText(const wxString& text) { - m_frame = frame; + wxString msg; + msg << wxTime().FormatTime() << ": " << text; + + // before doing any GUI calls we must ensure that this thread is the only + // one doing it! + wxMutexGuiEnter(); + m_frame->WriteText(msg); + wxMutexGuiLeave(); } void *MyThread::Entry() { - wxString text; + wxString text; + + DeferDestroy(TRUE); + + text.Printf("Thread 0x%x started.\n", GetID()); + WriteText(text); + + for ( m_count = 0; m_count < 20; m_count++ ) + { + // check if we were asked to exit + if ( TestDestroy() ) + break; + + text.Printf("[%u] Thread 0x%x here.\n", m_count, GetID()); + WriteText(text); + + wxSleep(1); + } - text.Printf("Thread 0x%x: Hello !\n", GetID()); - DeferDestroy(TRUE); + text.Printf("Thread 0x%x finished.\n", GetID()); + WriteText(text); - while (1) { - TestDestroy(); - text_mutex.Lock(); - m_frame->m_txtctrl->WriteText(text); - text_mutex.UnLock(); - wxSleep(1); - } - - return NULL; + return NULL; } // ID for the menu commands -#define TEST_QUIT 1 -#define TEST_TEXT 101 -#define TEST_ABOUT 102 -#define TEST_START_THREAD 103 -#define TEST_STOP_THREAD 104 -#define TEST_PAUSE_THREAD 105 +enum +{ + TEST_QUIT = 1, + TEST_TEXT = 101, + TEST_ABOUT = 102, + TEST_START_THREAD = 103, + TEST_STOP_THREAD = 104, + TEST_PAUSE_THREAD = 105, + TEST_RESUME_THREAD = 106 +}; BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(TEST_QUIT, MyFrame::OnQuit) - EVT_MENU(TEST_ABOUT, MyFrame::OnAbout) - EVT_MENU(TEST_START_THREAD, MyFrame::OnStartThread) - EVT_MENU(TEST_STOP_THREAD, MyFrame::OnStopThread) - EVT_MENU(TEST_PAUSE_THREAD, MyFrame::OnPauseThread) + EVT_MENU(TEST_QUIT, MyFrame::OnQuit) + EVT_MENU(TEST_ABOUT, MyFrame::OnAbout) + EVT_MENU(TEST_START_THREAD, MyFrame::OnStartThread) + EVT_MENU(TEST_STOP_THREAD, MyFrame::OnStopThread) + EVT_MENU(TEST_PAUSE_THREAD, MyFrame::OnPauseThread) + EVT_MENU(TEST_RESUME_THREAD, MyFrame::OnResumeThread) + + EVT_SIZE(MyFrame::OnSize) + + EVT_IDLE(MyFrame::OnIdle) END_EVENT_TABLE() // Create a new application object -IMPLEMENT_APP (MyApp) +IMPLEMENT_APP (MyApp) // `Main program' equivalent, creating windows and returning main app frame -bool MyApp::OnInit(void) +bool MyApp::OnInit() { - // Create the main frame window - MyFrame *frame = new MyFrame(NULL, "Minimal wxWindows App", 50, 50, 450, 340); + // Create the main frame window + MyFrame *frame = new MyFrame((wxFrame *)NULL, "", 50, 50, 450, 340); - // Give it an icon -#ifdef __WXMSW__ - frame->SetIcon(wxIcon("AIAI")); -#endif -#ifdef __X__ - frame->SetIcon(wxIcon("aiai.xbm")); -#endif - - // Make a menubar - wxMenu *file_menu = new wxMenu; - - file_menu->Append(TEST_ABOUT, "&About"); - file_menu->Append(TEST_QUIT, "E&xit"); - wxMenuBar *menu_bar = new wxMenuBar; - menu_bar->Append(file_menu, "&File"); + // Make a menubar + wxMenu *file_menu = new wxMenu; - wxMenu *thread_menu = new wxMenu; - thread_menu->Append(TEST_START_THREAD, "Start a new thread"); - thread_menu->Append(TEST_STOP_THREAD, "Stop a running thread"); - thread_menu->Append(TEST_PAUSE_THREAD, "Pause a running thread"); - menu_bar->Append(thread_menu, "Thread"); - frame->SetMenuBar(menu_bar); + file_menu->Append(TEST_ABOUT, "&About"); + file_menu->Append(TEST_QUIT, "E&xit"); + wxMenuBar *menu_bar = new wxMenuBar; + menu_bar->Append(file_menu, "&File"); - // Make a panel with a message - wxPanel *panel = new wxPanel(frame, -1, wxPoint(0, 0), wxSize(400, 200), wxTAB_TRAVERSAL); + wxMenu *thread_menu = new wxMenu; + thread_menu->Append(TEST_START_THREAD, "&Start a new thread"); + thread_menu->Append(TEST_STOP_THREAD, "S&top a running thread"); + thread_menu->AppendSeparator(); + thread_menu->Append(TEST_PAUSE_THREAD, "&Pause a running thread"); + thread_menu->Append(TEST_RESUME_THREAD, "&Resume suspended thread"); + menu_bar->Append(thread_menu, "&Thread"); + frame->SetMenuBar(menu_bar); - frame->m_txtctrl = new wxTextCtrl(panel, -1, "", wxPoint(10, 10), wxSize(390, 190), - wxTE_MULTILINE); + // Show the frame + frame->Show(TRUE); - // Show the frame - frame->Show(TRUE); - - SetTopWindow(frame); + SetTopWindow(frame); - return TRUE; + return TRUE; } // My frame constructor -MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h): - wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)) -{} +MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h) + : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)) +{ + wxPanel *panel = new wxPanel(this, -1, wxPoint(0, 0), wxSize(400, 200), + wxTAB_TRAVERSAL); + + m_txtctrl = new wxTextCtrl(panel, -1, "", wxPoint(10,30), wxSize(390, 190), + wxTE_MULTILINE); + + (void)new wxStaticText(panel, -1, "Log window", wxPoint(10,10)); +} void MyFrame::OnStartThread(wxCommandEvent& WXUNUSED(event) ) { - MyThread *thread = new MyThread(this); + MyThread *thread = new MyThread(this); - thread->Create(); + thread->Create(); - m_threads.Add(thread); + m_threads.Add(thread); } void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) ) { - int no_thrd = m_threads.Count()-1; + int no_thrd = m_threads.Count()-1; - if (no_thrd < 0) - return; + if (no_thrd < 0) + return; - delete (m_threads[no_thrd]); - m_threads.Remove(no_thrd); + delete m_threads[no_thrd]; + m_threads.Remove(no_thrd); +} + +void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) ) +{ + // resume first suspended thread + size_t n = 0; + while ( n < m_threads.Count() && m_threads[n]->IsPaused() ) + n--; + + if ( n < 0 ) + wxLogError("No thread to pause!"); + else + m_threads[n]->Resume(); } void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) ) -{} +{ + // pause last running thread + int n = m_threads.Count() - 1; + while ( n >= 0 && !m_threads[n]->IsRunning() ) + n--; + + if ( n < 0 ) + wxLogError("No thread to pause!"); + else + m_threads[n]->Pause(); +} + +// set the frame title indicating the current number of threads +void MyFrame::OnIdle(wxIdleEvent &event) +{ + size_t nRunning = 0, + nCount = m_threads.Count(); + for ( size_t n = 0; n < nCount; n++ ) + { + if ( m_threads[n]->IsRunning() ) + nRunning++; + } + + wxString title; + title.Printf("wxWindows thread sample (%u threads, %u running).", + nCount, nRunning); + SetTitle(title); +} + +void MyFrame::OnSize(wxSizeEvent& event) +{ + wxFrame::OnSize(event); + + wxSize size( GetClientSize() ); + + m_txtctrl->SetSize( 10, 30, size.x-20, size.y-40 ); +} void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) { - uint i; - for (i=0;i