Add support for thread-specific log targets.
A worker thread can now have its own log target which will be used directly by the log functions instead of buffering log output in the main thread; the GUI thread in the thread sample shows how it works. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61422 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
#include "wx/msgout.h"
|
||||
#include "wx/textfile.h"
|
||||
#include "wx/thread.h"
|
||||
#include "wx/private/threadinfo.h"
|
||||
#include "wx/crt.h"
|
||||
#include "wx/vector.h"
|
||||
|
||||
@@ -69,6 +70,8 @@ const char *wxLOG_COMPONENT = "";
|
||||
|
||||
#if wxUSE_THREADS
|
||||
|
||||
wxTLS_TYPE(wxThreadSpecificInfo) wxThreadInfoVar;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -259,31 +262,48 @@ wxLog::OnLog(wxLogLevel level,
|
||||
#endif
|
||||
}
|
||||
|
||||
wxLog *pLogger = GetActiveTarget();
|
||||
if ( !pLogger )
|
||||
return;
|
||||
wxLog *logger;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
wxCriticalSectionLocker lock(GetBackgroundLogCS());
|
||||
logger = wxThreadInfo.logger;
|
||||
if ( !logger )
|
||||
{
|
||||
if ( ms_pLogger )
|
||||
{
|
||||
// buffer the messages until they can be shown from the main
|
||||
// thread
|
||||
wxCriticalSectionLocker lock(GetBackgroundLogCS());
|
||||
|
||||
gs_bufferedLogRecords.push_back(wxLogRecord(level, msg, info));
|
||||
gs_bufferedLogRecords.push_back(wxLogRecord(level, msg, info));
|
||||
|
||||
// ensure that our Flush() will be called soon
|
||||
wxWakeUpIdle();
|
||||
// ensure that our Flush() will be called soon
|
||||
wxWakeUpIdle();
|
||||
}
|
||||
//else: we don't have any logger at all, there is no need to log
|
||||
// anything
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
//else: we have a thread-specific logger, we can send messages to it
|
||||
// directly
|
||||
}
|
||||
else
|
||||
#endif // wxUSE_THREADS
|
||||
{
|
||||
logger = ms_pLogger;
|
||||
if ( !logger )
|
||||
return;
|
||||
}
|
||||
|
||||
pLogger->OnLogInMainThread(level, msg, info);
|
||||
logger->CallDoLogNow(level, msg, info);
|
||||
}
|
||||
|
||||
void
|
||||
wxLog::OnLogInMainThread(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
wxLog::CallDoLogNow(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
if ( GetRepetitionCounting() )
|
||||
{
|
||||
@@ -429,6 +449,19 @@ void wxLog::DoLog(wxLogLevel WXUNUSED(level), const wchar_t *wzString, time_t t)
|
||||
|
||||
wxLog *wxLog::GetActiveTarget()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( !wxThread::IsMain() )
|
||||
{
|
||||
// check if we have a thread-specific log target
|
||||
wxLog * const logger = wxThreadInfo.logger;
|
||||
|
||||
// the code below should be only executed for the main thread as
|
||||
// CreateLogTarget() is not meant for auto-creating log targets for
|
||||
// worker threads so skip it in any case
|
||||
return logger ? logger : ms_pLogger;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
if ( ms_bAutoCreate && ms_pLogger == NULL ) {
|
||||
// prevent infinite recursion if someone calls wxLogXXX() from
|
||||
// wxApp::CreateLogTarget()
|
||||
@@ -465,6 +498,22 @@ wxLog *wxLog::SetActiveTarget(wxLog *pLogger)
|
||||
return pOldLogger;
|
||||
}
|
||||
|
||||
#if wxUSE_THREADS
|
||||
/* static */
|
||||
wxLog *wxLog::SetThreadActiveTarget(wxLog *logger)
|
||||
{
|
||||
wxASSERT_MSG( !wxThread::IsMain(), "use SetActiveTarget() for main thread" );
|
||||
|
||||
wxLog * const oldLogger = wxThreadInfo.logger;
|
||||
if ( oldLogger )
|
||||
oldLogger->Flush();
|
||||
|
||||
wxThreadInfo.logger = logger;
|
||||
|
||||
return oldLogger;
|
||||
}
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
void wxLog::DontCreateOnDemand()
|
||||
{
|
||||
ms_bAutoCreate = false;
|
||||
@@ -582,12 +631,10 @@ void wxLog::TimeStamp(wxString *str)
|
||||
#endif // wxUSE_DATETIME
|
||||
}
|
||||
|
||||
void wxLog::Flush()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
wxASSERT_MSG( wxThread::IsMain(),
|
||||
"should be called from the main thread only" );
|
||||
|
||||
void wxLog::FlushThreadMessages()
|
||||
{
|
||||
// check if we have queued messages from other threads
|
||||
wxLogRecords bufferedLogRecords;
|
||||
|
||||
@@ -605,14 +652,36 @@ void wxLog::Flush()
|
||||
it != bufferedLogRecords.end();
|
||||
++it )
|
||||
{
|
||||
OnLogInMainThread(it->level, it->msg, it->info);
|
||||
CallDoLogNow(it->level, it->msg, it->info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
void wxLog::Flush()
|
||||
{
|
||||
LogLastRepeatIfNeeded();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void wxLog::FlushActive()
|
||||
{
|
||||
if ( ms_suspendCount )
|
||||
return;
|
||||
|
||||
wxLog * const log = GetActiveTarget();
|
||||
if ( log )
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
if ( wxThread::IsMain() )
|
||||
log->FlushThreadMessages();
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
log->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxLogBuffer implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user