Files
qt6-migration-pipeline/Lts/DDS/FTC/generic_ftc_threading.cpp
T

331 lines
5.4 KiB
C++
Executable File

#include "generic_ftc_threading.h"
#include <QAtomicInt>
#include <QTimer>
#include <QRegularExpression>
#include <chrono>
#include <future>
#ifdef Q_OS_LINUX
#include <pthread.h>
#endif
Threading::~Threading()
{
if (m_threadLifetime != nullptr)
{
m_threadLifetime->stop();
m_threadLifetime.reset();
}
setCleanupNeeded(false);
{
std::lock_guard<std::mutex> l(m_conditionMutex);
setRun(false);
}
if (!m_used)
{
}
if (m_thread.joinable())
{
m_condition.notify_all();
m_thread.join();
}
}
void Threading::preInit() const
{
m_partitionId = partitionId();
m_partitionType = partitionType();
const QString base(QStringLiteral("F%1%2").arg(m_partitionType.left(1)).arg(m_partitionId));
const int baseLen = base.length();
const int maxLen = 16 - 1 - baseLen;
if (maxLen < 1)
{
Q_ASSERT(false);
m_threadName = functionTopicName();
return;
}
const QString orgName(functionTopicName());
QString name;
if (orgName.length() > maxLen)
{
QRegularExpression regexp(QStringLiteral("[A-Z][a-z]*"));
auto matches = regexp.globalMatch(functionTopicName());
QStringList words;
while (matches.hasNext())
{
const auto word = matches.next().capturedTexts().join(QString());
words += word;
}
if (words.isEmpty())
{
Q_ASSERT(false);
m_threadName = functionTopicName();
return;
}
int wordsLeft = words.count();
if (wordsLeft < 1)
{
Q_ASSERT(false);
m_threadName = functionTopicName();
return;
}
int bremse = 20;
while (wordsLeft > 0)
{
if (bremse < 1)
{
Q_ASSERT(false);
break;
}
bremse--;
const int lenRest = maxLen - name.count();
if (lenRest < 1)
{
Q_ASSERT(false);
m_threadName = functionTopicName();
return;
}
const int maxWordLen = lenRest / wordsLeft;
if (words.isEmpty())
{
Q_ASSERT(false);
break;
}
name += words.takeFirst().leftRef(maxWordLen);
wordsLeft--;
}
const int finalLeft = maxLen - name.count();
if (finalLeft < 0 || (finalLeft > 0 && functionTopicName().length() > maxLen))
{
}
}
else
{
name = orgName;
}
m_threadName = QStringLiteral("%1%2[%3]").arg(base, name).arg(qrand(), 8, 16, QLatin1Char('0'));
}
const QString &Threading::threadName() const
{
if (m_threadName.isEmpty())
{
Q_ASSERT(false);
}
return m_threadName;
}
const char *Threading::posixThreadName() const
{
if (m_posixThreadName.empty())
{
m_posixThreadName = threadName().left(15).toStdString();
}
return m_posixThreadName.c_str();
}
void Threading::createThread()
{
if (!isRun())
{
if (m_thread.joinable())
{
m_condition.notify_all();
m_thread.join();
threadDone();
}
m_alreadyThreaded = 0;
setRun(true);
m_thread = std::thread(&Threading::run, this, threadName());
#ifdef Q_OS_LINUX
pthread_setname_np(m_thread.native_handle(), posixThreadName());
#endif
}
m_createThreadCalledBefore = true;
}
void Threading::runThread()
{
m_used = true;
Q_ASSERT(m_createThreadCalledBefore);
m_createThreadCalledBefore = false;
{
std::lock_guard<std::mutex> l(m_conditionMutex);
setWorkAvailable(true);
}
m_condition.notify_all();
if (!m_threadLifetime)
{
m_threadLifetime.reset(new QTimer);
m_threadLifetime->setSingleShot(true);
m_threadLifetime->setInterval(11*1000);
QObject::connect(m_threadLifetime.get(), &QTimer::timeout, m_threadLifetime.get(),
[this]
{
bool workAvailable = false;
bool run = false;
bool working = false;
{
std::lock_guard<std::mutex> l(m_conditionMutex);
workAvailable = isWorkAvailable();
run = isRun();
working = isWorking();
}
if (workAvailable || working)
{
m_threadLifetime->start();
return;
}
m_threadLifetime->deleteLater();
m_threadLifetime = nullptr;
if (!run)
{
Q_ASSERT(false);
return;
}
{
std::lock_guard<std::mutex> l(m_conditionMutex);
setRun(false);
}
m_condition.notify_all();
});
}
m_threadLifetime->start();
}
void Threading::run(const QString &threadName)
{
Q_ASSERT(m_alreadyThreaded == 0);
m_alreadyThreaded = 1;
const std::string _tn = threadName.toStdString();
const char *tn = _tn.c_str();
while (isRun())
{
try
{
{
std::unique_lock<std::mutex> conditionLock(m_conditionMutex);
m_condition.wait(conditionLock, [this]{ return (isWorkAvailable() || !isRun()); });
}
cancellationPoint();
{
std::lock_guard<std::mutex> l(m_conditionMutex);
setWorking(true);
}
work();
{
std::lock_guard<std::mutex> l(m_conditionMutex);
setWorking(false);
}
cancellationPoint();
}
catch (const CancelationPointReached &ex)
{
break;
}
catch (const std::exception &ex)
{
fprintf(stderr, "[!] Threading::run: exception: %s (%s)\n", ex.what(), tn);
}
catch(...)
{
fprintf(stderr, "[!] Threading::run: unknown exception occured (%s) !!!\n", tn);
}
}
if (isCleanupNeeded())
{
cleanupThread();
}
else
{
}
}