mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 21:30:53 +00:00
Batch up output callbacks, instead of calling for every write
* If it's called every write then it risks spamming the system with signals and locking the UI thread with constant writes. Checking and flushing output every 100ms is sufficient.
This commit is contained in:
@@ -43,6 +43,7 @@ PyTypeObject **SbkPySide2_QtWidgetsTypes = NULL;
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include "PythonContext.h"
|
||||
#include "renderdoc_replay.h"
|
||||
|
||||
@@ -382,6 +383,20 @@ PythonContext::PythonContext(QObject *parent) : QObject(parent)
|
||||
|
||||
// release the GIL again
|
||||
PyGILState_Release(gil);
|
||||
|
||||
// every 100ms while running, check for new output
|
||||
outputTicker = new QTimer(this);
|
||||
outputTicker->setInterval(100);
|
||||
QObject::connect(outputTicker, &QTimer::timeout, this, &PythonContext::outputTick);
|
||||
|
||||
// we have to start it here, because we can't start on another thread.
|
||||
outputTicker->start();
|
||||
}
|
||||
|
||||
PythonContext::~PythonContext()
|
||||
{
|
||||
// do a final tick to gather any remaining output
|
||||
outputTick();
|
||||
}
|
||||
|
||||
void PythonContext::Finish()
|
||||
@@ -450,6 +465,9 @@ void PythonContext::executeString(const QString &filename, const QString &source
|
||||
|
||||
m_State = NULL;
|
||||
|
||||
// catch any output
|
||||
outputTick();
|
||||
|
||||
Py_XDECREF(thisobj);
|
||||
Py_XDECREF(traceContext);
|
||||
}
|
||||
@@ -587,6 +605,35 @@ PyObject *PythonContext::QtObjectToPython(const char *typeName, QObject *object)
|
||||
#endif
|
||||
}
|
||||
|
||||
// callback to flush output every so often (not constantly, to avoid spamming signals)
|
||||
void PythonContext::outputTick()
|
||||
{
|
||||
QMutexLocker lock(&outputMutex);
|
||||
|
||||
if(!outstr.isEmpty())
|
||||
{
|
||||
emit textOutput(false, outstr);
|
||||
}
|
||||
|
||||
if(!errstr.isEmpty())
|
||||
{
|
||||
emit textOutput(true, errstr);
|
||||
}
|
||||
|
||||
outstr.clear();
|
||||
errstr.clear();
|
||||
}
|
||||
|
||||
void PythonContext::addText(bool isStdError, const QString &output)
|
||||
{
|
||||
QMutexLocker lock(&outputMutex);
|
||||
|
||||
if(isStdError)
|
||||
errstr += output;
|
||||
else
|
||||
outstr += output;
|
||||
}
|
||||
|
||||
void PythonContext::setPyGlobal(const char *varName, PyObject *obj)
|
||||
{
|
||||
if(!initialised())
|
||||
@@ -662,7 +709,7 @@ PyObject *PythonContext::outstream_write(PyObject *self, PyObject *args)
|
||||
|
||||
if(context)
|
||||
{
|
||||
emit context->textOutput(redirector->isStdError ? true : false, QString::fromUtf8(text));
|
||||
context->addText(redirector->isStdError ? true : false, QString::fromUtf8(text));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
@@ -44,7 +45,8 @@ private:
|
||||
// don't allow destruction from outside, you must heap-allocate the context and let it delete
|
||||
// itself when all references are done. This handles the case where e.g. some Async work is going
|
||||
// on and needs to finish executing after the external code is done with the context
|
||||
~PythonContext() {}
|
||||
~PythonContext();
|
||||
|
||||
public:
|
||||
explicit PythonContext(QObject *parent = NULL);
|
||||
void Finish();
|
||||
@@ -121,6 +123,13 @@ private:
|
||||
|
||||
static PyObject *QtObjectToPython(const char *typeName, QObject *object);
|
||||
|
||||
QTimer *outputTicker;
|
||||
QMutex outputMutex;
|
||||
QString outstr, errstr;
|
||||
|
||||
void outputTick();
|
||||
void addText(bool isStdError, const QString &output);
|
||||
|
||||
// Python callbacks
|
||||
static void outstream_del(PyObject *self);
|
||||
static PyObject *outstream_write(PyObject *self, PyObject *args);
|
||||
|
||||
Reference in New Issue
Block a user