From: Robert Roebling Date: Thu, 30 Dec 1999 12:02:57 +0000 (+0000) Subject: Removed two more GUI lock-ups. This time when X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/ce6d2511f82aafc78aba320018c868f826ab172b Removed two more GUI lock-ups. This time when using on-GUI threads and sending event. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5151 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/samples/thread/test.cpp b/samples/thread/test.cpp index bf2769b807..7996d8f532 100644 --- a/samples/thread/test.cpp +++ b/samples/thread/test.cpp @@ -79,6 +79,9 @@ public: void OnStopThread(wxCommandEvent& event); void OnPauseThread(wxCommandEvent& event); void OnResumeThread(wxCommandEvent& event); + + void OnStartWorker(wxCommandEvent& event); + void OnWorkerEvent(wxCommandEvent& event); void OnIdle(wxIdleEvent &event); @@ -95,6 +98,26 @@ private: DECLARE_EVENT_TABLE() }; +// 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, + WORKER_EVENT // this one gets sent from the worker thread +}; + +//-------------------------------------------------- +// GUI thread +//-------------------------------------------------- + class MyThread : public wxThread { public: @@ -172,20 +195,61 @@ void *MyThread::Entry() return NULL; } -// ID for the menu commands -enum +//-------------------------------------------------- +// worker thread +//-------------------------------------------------- + +class MyWorkerThread : public wxThread { - 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 +public: + MyWorkerThread(MyFrame *frame); + + // 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(); + +public: + MyFrame *m_frame; + size_t m_count; }; +MyWorkerThread::MyWorkerThread(MyFrame *frame) + : wxThread() +{ + m_frame = frame; + m_count = 0; +} + +void MyWorkerThread::OnExit() +{ +} + +void *MyWorkerThread::Entry() +{ + for ( m_count = 0; m_count < 10; m_count++ ) + { + // check if we were asked to exit + if ( TestDestroy() ) + break; + + wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT ); + event.SetInt( WORKER_EVENT ); + wxPostEvent( m_frame, event ); + + // wxSleep() can't be called from non-GUI thread! + wxThread::Sleep(1000); + } + + return NULL; +} + +//-------------------------------------------------- +// main program +//-------------------------------------------------- + BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(TEST_QUIT, MyFrame::OnQuit) EVT_MENU(TEST_ABOUT, MyFrame::OnAbout) @@ -195,6 +259,9 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(TEST_STOP_THREAD, MyFrame::OnStopThread) EVT_MENU(TEST_PAUSE_THREAD, MyFrame::OnPauseThread) EVT_MENU(TEST_RESUME_THREAD, MyFrame::OnResumeThread) + + EVT_MENU(TEST_START_WORKER, MyFrame::OnStartWorker) + EVT_MENU(WORKER_EVENT, MyFrame::OnWorkerEvent) EVT_IDLE(MyFrame::OnIdle) END_EVENT_TABLE() @@ -224,6 +291,9 @@ bool MyApp::OnInit() 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); @@ -436,3 +506,21 @@ void MyFrame::OnClear(wxCommandEvent& WXUNUSED(event)) { m_txtctrl->Clear(); } + +void MyFrame::OnStartWorker(wxCommandEvent& WXUNUSED(event)) +{ + MyWorkerThread *thread = new MyWorkerThread(this); + + if ( thread->Create() != wxTHREAD_NO_ERROR ) + { + wxLogError("Can't create thread!"); + } + + thread->Run(); +} + +void MyFrame::OnWorkerEvent(wxCommandEvent& WXUNUSED(event)) +{ + WriteText( "Got message from worker thread\n" ); +} + diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index b01cdd229c..d185f5bff0 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -63,7 +63,7 @@ void wxAppBase::ProcessPendingEvents() delete node; // In ProcessPendingEvents(), new handlers might be add - // and we can safely leave the critical section here. + // and we can safely leave the critical section here. wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); handler->ProcessPendingEvents(); wxENTER_CRIT_SECT( *wxPendingEventsLocker ); diff --git a/src/common/event.cpp b/src/common/event.cpp index f657f889e1..97f135ff08 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -644,12 +644,11 @@ void wxEvtHandler::AddPendingEvent(wxEvent& event) wxPendingEvents = new wxList; wxPendingEvents->Append(this); + wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); + // 3) Inform the system that new pending events are somwehere, // and that these should be processed in idle time. - wxWakeUpIdle(); - - wxLEAVE_CRIT_SECT(*wxPendingEventsLocker); } void wxEvtHandler::ProcessPendingEvents() @@ -667,7 +666,7 @@ void wxEvtHandler::ProcessPendingEvents() delete node; // In ProcessEvent, new events might get added and - // we can safely leave the crtical section here. + // we can safely leave the crtical section here. #if defined(__VISAGECPP__) wxLEAVE_CRIT_SECT( m_eventsLocker); #else diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index 965f9967f2..43a5a92aa9 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -111,7 +111,7 @@ void wxWakeUpIdle() { #if wxUSE_THREADS if (!wxThread::IsMain()) - gdk_threads_enter(); + wxMutexGuiEnter(); #endif if (g_isIdle) @@ -119,7 +119,7 @@ void wxWakeUpIdle() #if wxUSE_THREADS if (!wxThread::IsMain()) - gdk_threads_leave(); + wxMutexGuiLeave(); #endif } @@ -178,7 +178,7 @@ void wxapp_install_thread_wakeup() { if (wxTheApp->m_wakeUpTimerTag) return; - wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 50, wxapp_wakeup_timerout_callback, (gpointer) NULL ); + wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 500, wxapp_wakeup_timerout_callback, (gpointer) NULL ); } void wxapp_uninstall_thread_wakeup() @@ -194,7 +194,6 @@ gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) ) // when getting called from GDK's time-out handler // we are no longer within GDK's grab on the GUI // thread so we must lock it here ourselves - gdk_threads_enter(); wxapp_uninstall_thread_wakeup(); diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index 965f9967f2..43a5a92aa9 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -111,7 +111,7 @@ void wxWakeUpIdle() { #if wxUSE_THREADS if (!wxThread::IsMain()) - gdk_threads_enter(); + wxMutexGuiEnter(); #endif if (g_isIdle) @@ -119,7 +119,7 @@ void wxWakeUpIdle() #if wxUSE_THREADS if (!wxThread::IsMain()) - gdk_threads_leave(); + wxMutexGuiLeave(); #endif } @@ -178,7 +178,7 @@ void wxapp_install_thread_wakeup() { if (wxTheApp->m_wakeUpTimerTag) return; - wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 50, wxapp_wakeup_timerout_callback, (gpointer) NULL ); + wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 500, wxapp_wakeup_timerout_callback, (gpointer) NULL ); } void wxapp_uninstall_thread_wakeup() @@ -194,7 +194,6 @@ gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) ) // when getting called from GDK's time-out handler // we are no longer within GDK's grab on the GUI // thread so we must lock it here ourselves - gdk_threads_enter(); wxapp_uninstall_thread_wakeup();