X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c4f02b1fd84a243002416902530d9fed73ac7147..19e30148e18cc99296b26503c155e5cef59045f4:/samples/thread/thread.cpp diff --git a/samples/thread/thread.cpp b/samples/thread/thread.cpp index d53bbca802..48aef6531e 100644 --- a/samples/thread/thread.cpp +++ b/samples/thread/thread.cpp @@ -14,11 +14,6 @@ messages - it will be more visual */ -#ifdef __GNUG__ - #pragma implementation "thread.cpp" - #pragma interface "thread.cpp" -#endif - // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -40,8 +35,12 @@ #include "wx/progdlg.h" -// uncomment this to get some debugging messages from the trace code -//#define TRACE +#define USE_EXECUTE +#ifdef USE_EXECUTE + #define EXEC(cmd) wxExecute((cmd), wxEXEC_SYNC) +#else + #define EXEC(cmd) system(cmd) +#endif class MyThread; WX_DEFINE_ARRAY(wxThread *, wxArrayThread); @@ -79,7 +78,6 @@ public: // callbacks void OnQuit(wxCommandEvent& event); - void OnAbout(wxCommandEvent& event); void OnClear(wxCommandEvent& event); void OnStartThread(wxCommandEvent& event); @@ -92,6 +90,12 @@ public: void OnWorkerEvent(wxCommandEvent& event); void OnUpdateWorker(wxUpdateUIEvent& event); + void OnExecMain(wxCommandEvent& event); + void OnExecThread(wxCommandEvent& event); + + void OnShowCPUs(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + void OnIdle(wxIdleEvent &event); private: @@ -119,22 +123,28 @@ private: // ID for the menu commands enum { - TEST_QUIT = 1, - TEST_TEXT = 101, - TEST_ABOUT, - TEST_CLEAR, - TEST_START_THREAD = 201, - TEST_START_THREADS, - TEST_STOP_THREAD, - TEST_PAUSE_THREAD, - TEST_RESUME_THREAD, - TEST_START_WORKER, + THREAD_QUIT = 1, + THREAD_TEXT = 101, + THREAD_CLEAR, + THREAD_START_THREAD = 201, + THREAD_START_THREADS, + THREAD_STOP_THREAD, + THREAD_PAUSE_THREAD, + THREAD_RESUME_THREAD, + THREAD_START_WORKER, + + THREAD_EXEC_MAIN, + THREAD_EXEC_THREAD, + + THREAD_SHOWCPUS, + THREAD_ABOUT, + WORKER_EVENT // this one gets sent from the worker thread }; -//-------------------------------------------------- +// ---------------------------------------------------------------------------- // GUI thread -//-------------------------------------------------- +// ---------------------------------------------------------------------------- class MyThread : public wxThread { @@ -189,7 +199,7 @@ void *MyThread::Entry() { wxString text; - text.Printf("Thread 0x%x started (priority = %d).\n", + text.Printf(wxT("Thread 0x%x started (priority = %d).\n"), GetId(), GetPriority()); WriteText(text); // wxLogMessage(text); -- test wxLog thread safeness @@ -200,23 +210,23 @@ void *MyThread::Entry() if ( TestDestroy() ) break; - text.Printf("[%u] Thread 0x%x here.\n", m_count, GetId()); + text.Printf(wxT("[%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(wxT("Thread 0x%x finished.\n"), GetId()); WriteText(text); // wxLogMessage(text); -- test wxLog thread safeness return NULL; } -//-------------------------------------------------- +// ---------------------------------------------------------------------------- // worker thread -//-------------------------------------------------- +// ---------------------------------------------------------------------------- class MyWorkerThread : public wxThread { @@ -254,20 +264,13 @@ void *MyWorkerThread::Entry() if ( TestDestroy() ) break; - wxString text; - text.Printf("[%u] Thread 0x%x here!!", m_count, GetId()); - // create any type of command event here wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT ); event.SetInt( m_count ); - event.SetString( text ); // send in a thread-safe way wxPostEvent( m_frame, event ); - // same as: - // m_frame->AddPendingEvent( event ); - // wxSleep() can't be called from non-main thread! wxThread::Sleep(200); } @@ -279,22 +282,49 @@ void *MyWorkerThread::Entry() return NULL; } -//-------------------------------------------------- -// main program -//-------------------------------------------------- +// ---------------------------------------------------------------------------- +// a thread which simply calls wxExecute +// ---------------------------------------------------------------------------- + +class MyExecThread : public wxThread +{ +public: + MyExecThread(const wxChar *command) : wxThread(wxTHREAD_JOINABLE), + m_command(command) + { + Create(); + } + + virtual ExitCode Entry() + { + return (ExitCode)EXEC(m_command); + } + +private: + wxString m_command; +}; + +// ---------------------------------------------------------------------------- +// implementation +// ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(TEST_QUIT, MyFrame::OnQuit) - EVT_MENU(TEST_ABOUT, MyFrame::OnAbout) - EVT_MENU(TEST_CLEAR, MyFrame::OnClear) - EVT_MENU(TEST_START_THREAD, MyFrame::OnStartThread) - EVT_MENU(TEST_START_THREADS, MyFrame::OnStartThreads) - EVT_MENU(TEST_STOP_THREAD, MyFrame::OnStopThread) - EVT_MENU(TEST_PAUSE_THREAD, MyFrame::OnPauseThread) - EVT_MENU(TEST_RESUME_THREAD, MyFrame::OnResumeThread) - - EVT_UPDATE_UI(TEST_START_WORKER, MyFrame::OnUpdateWorker) - EVT_MENU(TEST_START_WORKER, MyFrame::OnStartWorker) + EVT_MENU(THREAD_QUIT, MyFrame::OnQuit) + EVT_MENU(THREAD_CLEAR, MyFrame::OnClear) + EVT_MENU(THREAD_START_THREAD, MyFrame::OnStartThread) + EVT_MENU(THREAD_START_THREADS, MyFrame::OnStartThreads) + EVT_MENU(THREAD_STOP_THREAD, MyFrame::OnStopThread) + EVT_MENU(THREAD_PAUSE_THREAD, MyFrame::OnPauseThread) + EVT_MENU(THREAD_RESUME_THREAD, MyFrame::OnResumeThread) + + EVT_MENU(THREAD_EXEC_MAIN, MyFrame::OnExecMain) + EVT_MENU(THREAD_EXEC_THREAD, MyFrame::OnExecThread) + + EVT_MENU(THREAD_SHOWCPUS, MyFrame::OnShowCPUs) + EVT_MENU(THREAD_ABOUT, MyFrame::OnAbout) + + EVT_UPDATE_UI(THREAD_START_WORKER, MyFrame::OnUpdateWorker) + EVT_MENU(THREAD_START_WORKER, MyFrame::OnStartWorker) EVT_MENU(WORKER_EVENT, MyFrame::OnWorkerEvent) EVT_IDLE(MyFrame::OnIdle) @@ -303,37 +333,46 @@ END_EVENT_TABLE() // `Main program' equivalent, creating windows and returning main app frame bool MyApp::OnInit() { -#ifdef TRACE - wxLog::AddTraceMask("thread"); -#endif + // uncomment this to get some debugging messages from the trace code + // on the console (or just set WXTRACE env variable to include "thread") + //wxLog::AddTraceMask("thread"); // Create the main frame window MyFrame *frame = new MyFrame((wxFrame *)NULL, "wxWindows threads sample", 50, 50, 450, 340); // Make a menubar - wxMenu *file_menu = new wxMenu; - - 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\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\tCtrl-N"); - thread_menu->Append(TEST_START_THREADS, "Start &many threads at once"); - 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\tCtrl-P"); - thread_menu->Append(TEST_RESUME_THREAD, "&Resume suspended thread\tCtrl-R"); - thread_menu->AppendSeparator(); - thread_menu->Append(TEST_START_WORKER, "Start &worker thread\tCtrl-W"); - - menu_bar->Append(thread_menu, "&Thread"); - frame->SetMenuBar(menu_bar); + wxMenuBar *menuBar = new wxMenuBar; + + wxMenu *menuFile = new wxMenu; + menuFile->Append(THREAD_CLEAR, "&Clear log\tCtrl-L"); + menuFile->AppendSeparator(); + menuFile->Append(THREAD_QUIT, "E&xit\tAlt-X"); + menuBar->Append(menuFile, "&File"); + + wxMenu *menuThread = new wxMenu; + menuThread->Append(THREAD_START_THREAD, "&Start a new thread\tCtrl-N"); + menuThread->Append(THREAD_START_THREADS, "Start &many threads at once"); + menuThread->Append(THREAD_STOP_THREAD, "S&top a running thread\tCtrl-S"); + menuThread->AppendSeparator(); + menuThread->Append(THREAD_PAUSE_THREAD, "&Pause a running thread\tCtrl-P"); + menuThread->Append(THREAD_RESUME_THREAD, "&Resume suspended thread\tCtrl-R"); + menuThread->AppendSeparator(); + menuThread->Append(THREAD_START_WORKER, "Start &worker thread\tCtrl-W"); + menuBar->Append(menuThread, "&Thread"); + + wxMenu *menuExec = new wxMenu; + menuExec->Append(THREAD_EXEC_MAIN, "&Launch a program from main thread\tF5"); + menuExec->Append(THREAD_EXEC_THREAD, "L&aunch a program from a thread\tCtrl-F5"); + menuBar->Append(menuExec, "&Execute"); + + wxMenu *menuHelp = new wxMenu; + menuHelp->Append(THREAD_SHOWCPUS, "&Show CPU count"); + menuHelp->AppendSeparator(); + menuHelp->Append(THREAD_ABOUT, "&About..."); + menuBar->Append(menuHelp, "&Help"); + + frame->SetMenuBar(menuBar); // Show the frame frame->Show(TRUE); @@ -365,7 +404,7 @@ MyThread *MyFrame::CreateThread() if ( thread->Create() != wxTHREAD_NO_ERROR ) { - wxLogError("Can't create thread!"); + wxLogError(wxT("Can't create thread!")); } wxCriticalSectionLocker enter(wxGetApp().m_critsect); @@ -410,7 +449,7 @@ void MyFrame::OnStartThreads(wxCommandEvent& WXUNUSED(event) ) } wxString msg; - msg.Printf("%d new threads created.", count); + msg.Printf(wxT("%d new threads created."), count); SetStatusText(msg, 1); // ...and then start them @@ -426,7 +465,7 @@ void MyFrame::OnStartThread(wxCommandEvent& WXUNUSED(event) ) if ( thread->Run() != wxTHREAD_NO_ERROR ) { - wxLogError("Can't start thread!"); + wxLogError(wxT("Can't start thread!")); } SetStatusText("New thread started.", 1); @@ -439,7 +478,7 @@ void MyFrame::OnStopThread(wxCommandEvent& WXUNUSED(event) ) // stop the last thread if ( wxGetApp().m_threads.IsEmpty() ) { - wxLogError("No thread to stop!"); + wxLogError(wxT("No thread to stop!")); wxGetApp().m_critsect.Leave(); } @@ -469,7 +508,7 @@ void MyFrame::OnResumeThread(wxCommandEvent& WXUNUSED(event) ) if ( n == count ) { - wxLogError("No thread to resume!"); + wxLogError(wxT("No thread to resume!")); } else { @@ -490,7 +529,7 @@ void MyFrame::OnPauseThread(wxCommandEvent& WXUNUSED(event) ) if ( n < 0 ) { - wxLogError("No thread to pause!"); + wxLogError(wxT("No thread to pause!")); } else { @@ -517,7 +556,7 @@ void MyFrame::OnIdle(wxIdleEvent &event) m_nRunning = nRunning; m_nCount = nCount; - wxLogStatus(this, "%u threads total, %u running.", nCount, nRunning); + wxLogStatus(this, wxT("%u threads total, %u running."), nCount, nRunning); } //else: avoid flicker - don't print anything } @@ -533,6 +572,47 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) Close(TRUE); } +void MyFrame::OnExecMain(wxCommandEvent& WXUNUSED(event)) +{ + wxLogMessage("The exit code from the main program is %ld", + EXEC("/bin/echo \"main program\"")); +} + +void MyFrame::OnExecThread(wxCommandEvent& WXUNUSED(event)) +{ + MyExecThread thread("/bin/echo \"child thread\""); + thread.Run(); + + wxLogMessage("The exit code from a child thread is %ld", + (long)thread.Wait()); +} + +void MyFrame::OnShowCPUs(wxCommandEvent& WXUNUSED(event)) +{ + wxString msg; + + int nCPUs = wxThread::GetCPUCount(); + switch ( nCPUs ) + { + case -1: + msg = "Unknown number of CPUs"; + break; + + case 0: + msg = "WARNING: you're running without any CPUs!"; + break; + + case 1: + msg = "This system only has one CPU."; + break; + + default: + msg.Printf("This system has %d CPUs", nCPUs); + } + + wxLogMessage(msg); +} + void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) { wxMessageDialog dialog(this, "wxWindows multithreaded application sample\n" @@ -547,11 +627,6 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event)) { -#ifdef TRACE - // log a separator - wxLogTrace("-------- log window cleared --------"); -#endif - m_txtctrl->Clear(); } @@ -566,7 +641,7 @@ void MyFrame::OnStartWorker(wxCommandEvent& WXUNUSED(event)) if ( thread->Create() != wxTHREAD_NO_ERROR ) { - wxLogError("Can't create thread!"); + wxLogError(wxT("Can't create thread!")); } m_dlgProgress = new wxProgressDialog