make wxLogWindow thread-safe (#8783)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54019 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
a96bab36bf
commit
cd1ff792d2
@ -299,6 +299,7 @@ All (GUI):
|
||||
- Added support for labels for toolbar controls (Vince Harron).
|
||||
- Added wxMessageDialog::SetMessage() and SetExtendedMessage().
|
||||
- Added wxListCtrl::Set/GetColumnsOrder() (Yury Voronov)
|
||||
- Made wxLogWindow thread-safe (Barbara Maren Winkler).
|
||||
- Added wxWindow::AlwaysShowScrollbars() (Julian Scheid)
|
||||
- Added wxMouseEvent::GetClickCount() (Julian Scheid)
|
||||
- Added wxBG_STYLE_TRANSPARENT background style (Julian Scheid)
|
||||
|
@ -48,12 +48,18 @@
|
||||
#include "wx/statline.h"
|
||||
#include "wx/artprov.h"
|
||||
#include "wx/collpane.h"
|
||||
#include "wx/arrstr.h"
|
||||
|
||||
#if wxUSE_THREADS
|
||||
#include "wx/thread.h"
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// for OutputDebugString()
|
||||
#include "wx/msw/private.h"
|
||||
#endif // Windows
|
||||
|
||||
|
||||
#ifdef __WXPM__
|
||||
#include <time.h>
|
||||
#endif
|
||||
@ -478,8 +484,14 @@ public:
|
||||
#endif // wxUSE_FILE
|
||||
void OnClear(wxCommandEvent& event);
|
||||
|
||||
// accessors
|
||||
wxTextCtrl *TextCtrl() const { return m_pTextCtrl; }
|
||||
// this function is safe to call from any thread (notice that it should be
|
||||
// also called from the main thread to ensure that the messages logged from
|
||||
// it appear in correct order with the messages from the other threads)
|
||||
void AddLogMessage(const wxString& message);
|
||||
|
||||
// actually append the messages logged from secondary threads to the text
|
||||
// control during idle time in the main thread
|
||||
virtual void OnInternalIdle();
|
||||
|
||||
private:
|
||||
// use standard ids for our commands!
|
||||
@ -493,9 +505,24 @@ private:
|
||||
// common part of OnClose() and OnCloseWindow()
|
||||
void DoClose();
|
||||
|
||||
// do show the message in the text control
|
||||
void DoShowLogMessage(const wxString& message)
|
||||
{
|
||||
m_pTextCtrl->AppendText(message);
|
||||
}
|
||||
|
||||
wxTextCtrl *m_pTextCtrl;
|
||||
wxLogWindow *m_log;
|
||||
|
||||
// queue of messages logged from other threads which need to be displayed
|
||||
wxArrayString m_pendingMessages;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
// critical section to protect access to m_pendingMessages
|
||||
wxCriticalSection m_critSection;
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
DECLARE_NO_COPY_CLASS(wxLogFrame)
|
||||
};
|
||||
@ -610,6 +637,43 @@ void wxLogFrame::OnClear(wxCommandEvent& WXUNUSED(event))
|
||||
m_pTextCtrl->Clear();
|
||||
}
|
||||
|
||||
void wxLogFrame::OnInternalIdle()
|
||||
{
|
||||
{
|
||||
wxCRIT_SECT_LOCKER(locker, m_critSection);
|
||||
|
||||
const size_t count = m_pendingMessages.size();
|
||||
for ( size_t n = 0; n < count; n++ )
|
||||
{
|
||||
DoShowLogMessage(m_pendingMessages[n]);
|
||||
}
|
||||
|
||||
m_pendingMessages.clear();
|
||||
} // release m_critSection
|
||||
|
||||
wxFrame::OnInternalIdle();
|
||||
}
|
||||
|
||||
void wxLogFrame::AddLogMessage(const wxString& message)
|
||||
{
|
||||
wxCRIT_SECT_LOCKER(locker, m_critSection);
|
||||
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() || !m_pendingMessages.empty() )
|
||||
{
|
||||
// message needs to be queued for later showing
|
||||
m_pendingMessages.Add(message);
|
||||
|
||||
wxWakeUpIdle();
|
||||
}
|
||||
else // we are the main thread and no messages are queued, so we can
|
||||
// log the message directly
|
||||
#endif // wxUSE_THREADS
|
||||
{
|
||||
DoShowLogMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
wxLogFrame::~wxLogFrame()
|
||||
{
|
||||
m_log->OnFrameDelete(this);
|
||||
@ -670,22 +734,12 @@ void wxLogWindow::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
|
||||
void wxLogWindow::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
{
|
||||
// put the text into our window
|
||||
wxTextCtrl *pText = m_pLogFrame->TextCtrl();
|
||||
|
||||
// remove selection (WriteText is in fact ReplaceSelection)
|
||||
#ifdef __WXMSW__
|
||||
wxTextPos nLen = pText->GetLastPosition();
|
||||
pText->SetSelection(nLen, nLen);
|
||||
#endif // Windows
|
||||
|
||||
wxString msg;
|
||||
|
||||
TimeStamp(&msg);
|
||||
msg << szString << wxT('\n');
|
||||
|
||||
pText->AppendText(msg);
|
||||
|
||||
// TODO ensure that the line can be seen
|
||||
m_pLogFrame->AddLogMessage(msg);
|
||||
}
|
||||
|
||||
wxFrame *wxLogWindow::GetFrame() const
|
||||
@ -998,7 +1052,7 @@ void wxLogDialog::OnListItemActivated(wxListEvent& event)
|
||||
// as there's a 260 chars limit on the items inside a wxListCtrl in wxMSW.
|
||||
wxString str = m_messages[event.GetIndex()];
|
||||
|
||||
// wxMessageBox will nicely handle the '\n' in the string (if any)
|
||||
// wxMessageBox will nicely handle the '\n' in the string (if any)
|
||||
// and supports long strings
|
||||
wxMessageBox(str, wxT("Log message"), wxOK, this);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user