92 lines
1.8 KiB
C++
92 lines
1.8 KiB
C++
#include "streamfsm.h"
|
|
|
|
StreamFsm::StreamFsm(RestartPolicy policy, QObject *parent)
|
|
: QObject(parent)
|
|
, m_policy(policy)
|
|
{
|
|
}
|
|
|
|
StreamFsm::~StreamFsm()
|
|
{
|
|
stop();
|
|
}
|
|
|
|
void StreamFsm::start(const QString &program, const QStringList &args)
|
|
{
|
|
m_program = program;
|
|
m_args = args;
|
|
if (m_state == Idle)
|
|
startProcess();
|
|
}
|
|
|
|
void StreamFsm::stop()
|
|
{
|
|
if (m_state == Idle)
|
|
return;
|
|
|
|
if (m_proc) {
|
|
// Disconnect before killing so onFinished doesn't fire during teardown.
|
|
m_proc->disconnect();
|
|
m_proc->kill();
|
|
m_proc->waitForFinished(1000);
|
|
m_proc->deleteLater();
|
|
m_proc = nullptr;
|
|
}
|
|
transitTo(Idle);
|
|
}
|
|
|
|
void StreamFsm::setGuard(std::function<bool()> guard)
|
|
{
|
|
m_guard = std::move(guard);
|
|
}
|
|
|
|
void StreamFsm::startProcess()
|
|
{
|
|
if (m_state != Idle)
|
|
return;
|
|
|
|
m_proc = new QProcess(this);
|
|
connect(m_proc, &QProcess::readyReadStandardOutput,
|
|
this, &StreamFsm::onReadyRead);
|
|
connect(m_proc,
|
|
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
|
this, &StreamFsm::onFinished);
|
|
m_proc->start(m_program, m_args);
|
|
transitTo(Running);
|
|
}
|
|
|
|
void StreamFsm::onReadyRead()
|
|
{
|
|
QByteArray data = m_proc->readAllStandardOutput();
|
|
if (!data.isEmpty())
|
|
emit readyRead(data);
|
|
}
|
|
|
|
void StreamFsm::onFinished(int, QProcess::ExitStatus)
|
|
{
|
|
// Clean up the finished process.
|
|
m_proc->deleteLater();
|
|
m_proc = nullptr;
|
|
transitTo(Idle);
|
|
|
|
// Decide what to do next based on policy.
|
|
switch (m_policy) {
|
|
case Oneshot:
|
|
emit died();
|
|
break;
|
|
case Looping:
|
|
startProcess();
|
|
break;
|
|
case Guarded:
|
|
if (m_guard && m_guard())
|
|
startProcess();
|
|
else
|
|
emit died();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StreamFsm::transitTo(State s)
|
|
{
|
|
m_state = s;
|
|
} |