From f2fa0746a2862f5f977e8c7c10a41a6ccb5bf87b Mon Sep 17 00:00:00 2001 From: hehaoyang <1109196436@qq.com> Date: Thu, 11 Jan 2024 16:14:21 +0800 Subject: [PATCH] first commit --- .gitignore | 7 ++ HxDisk.cpp | 113 ++++++++++++++++++++++++++ HxDisk.h | 65 +++++++++++++++ HxLog.cpp | 26 ++++++ HxLog.h | 15 ++++ HxProcess.cpp | 40 +++++++++ HxProcess.h | 19 +++++ HxSocket.cpp | 93 +++++++++++++++++++++ HxSocket.h | 41 ++++++++++ HxSql.cpp | 38 +++++++++ HxSql.h | 24 ++++++ HxSystem.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++ HxSystem.h | 84 +++++++++++++++++++ HxTask.cpp | 7 ++ HxTask.h | 191 +++++++++++++++++++++++++++++++++++++++++++ HxThread.cpp | 40 +++++++++ HxThread.h | 60 ++++++++++++++ HxTrace.cpp | 35 ++++++++ HxTrace.h | 24 ++++++ HxUtils.pro | 57 +++++++++++++ 20 files changed, 1197 insertions(+) create mode 100644 .gitignore create mode 100644 HxDisk.cpp create mode 100644 HxDisk.h create mode 100644 HxLog.cpp create mode 100644 HxLog.h create mode 100644 HxProcess.cpp create mode 100644 HxProcess.h create mode 100644 HxSocket.cpp create mode 100644 HxSocket.h create mode 100644 HxSql.cpp create mode 100644 HxSql.h create mode 100644 HxSystem.cpp create mode 100644 HxSystem.h create mode 100644 HxTask.cpp create mode 100644 HxTask.h create mode 100644 HxThread.cpp create mode 100644 HxThread.h create mode 100644 HxTrace.cpp create mode 100644 HxTrace.h create mode 100644 HxUtils.pro diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..133446b --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +debug/* +release/* +.qmake.stash +HxUtils.pro.* +Makefile* +*.Debug +*.Release \ No newline at end of file diff --git a/HxDisk.cpp b/HxDisk.cpp new file mode 100644 index 0000000..46ff3b4 --- /dev/null +++ b/HxDisk.cpp @@ -0,0 +1,113 @@ +#include "HxDisk.h" + +void HxDisk::mkpath(QString path) +{ + QDir dir; + + if (!dir.exists(path)) + dir.mkpath(path); +} + + +void HxDisk::mkpath(QStringList names) +{ + foreach (QString name, names) { + HxDisk::mkpath(name); + } +} + +bool HxDisk::exist(QString rootPath) +{ + foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) + { + if (rootPath == storage.rootPath()) + return true; + } + + return false; +} + + +bool HxDisk::empty(QString path) +{ + return QDir(path).removeRecursively(); +} + +QList HxDisk::mounted_volumes() +{ + QList storageinfos; + foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) + { + if (storage.isValid() && + storage.isReady() && + !storage.rootPath().isNull() && + !storage.isReadOnly()) + { +#ifndef Q_OS_WIN32 + if (storage.rootPath() == "/") + continue; + + if (storage.fileSystemType() != "ext4") + continue; +#endif + storageinfos.append(storage); + } + } + + return storageinfos; +} + +double HxDisk::total_size(QString rootPath) +{ + foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) + { + if (rootPath == storage.rootPath()) + return static_cast(storage.bytesTotal()) / 1024 / 1024 / 1024; + } + + return 0; +} + +double HxDisk::free_size(QString rootPath) +{ + foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) + { + if (rootPath == storage.rootPath()) + return static_cast(storage.bytesAvailable()) / 1024 / 1024 / 1024; + } + + return 0; +} + +int HxDisk::entry_info_list(QString path) +{ + QDir dir(path); + if (!dir.exists()) + return 0; + + /* 设置过滤器 */ + dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); + + return dir.entryInfoList().count(); +} + +void HxDisk::remove(QString filepath) +{ + QFileInfo fileinfo(filepath); + + if (!fileinfo.exists()) + return; + + QFile::remove(fileinfo.filePath()); + + QDir dir(fileinfo.path()); + + while (entry_info_list(dir.path()) == 0) + { + dir.rmdir(dir.path()); + + /* 返回上一级目录 */ + if (!dir.cdUp()) + return; + } +} diff --git a/HxDisk.h b/HxDisk.h new file mode 100644 index 0000000..33ca507 --- /dev/null +++ b/HxDisk.h @@ -0,0 +1,65 @@ +#ifndef HXDISK_H +#define HXDISK_H + +#include "HxTrace.h" + +#include +#include + +class HxDisk +{ +public: + /** + * @brief 创建文件夹 + * @param path 路径 + */ + static void mkpath(QString path); + + + static void mkpath(QStringList names); + + /** + * @brief 判断盘符是否存在 + * @param rootPath 路径 + * @return + */ + static bool exist(QString rootPath); + + + static bool empty(QString path); + + /** + * @brief 遍历盘符信息 + * @return 返回磁盘信息 + */ + static QList mounted_volumes(); + + /** + * @brief 获取磁盘总空间大小 + * @param rootPath 路径 + * @return 总空间, 单位: G + */ + static double total_size(QString rootPath); + + /** + * @brief 获取磁盘剩余空间大小 + * @param rootPath 路径 + * @return 剩余空间, 单位: G + */ + static double free_size(QString rootPath); + + /** + * @brief 检索目录信息总数 + * @param path 目录路径 + * @return 文件总数 + */ + static int entry_info_list(QString path); + + /** + * @brief 删除文件并判断目录是否为空, 为空时删除目录 + * @param filepath 文件路径 + */ + static void remove(QString filepath); +}; + +#endif diff --git a/HxLog.cpp b/HxLog.cpp new file mode 100644 index 0000000..f8b7cf8 --- /dev/null +++ b/HxLog.cpp @@ -0,0 +1,26 @@ +#include "HxLog.h" + +#include +#include + +QMutex HxLog::mutex; + +void HxLog::append(QString title, QString message) +{ + mutex.lock(); + + auto current_time = QDateTime::currentDateTime(); + + QFile file(QString("log/%1.log").arg(current_time.toString("yyyyMMdd"))); + + if (file.open(QIODevice::WriteOnly | QIODevice::Append)) + { + auto data = QString("[%1] | [%2] | %3\r\n").arg(current_time.toString("yyyy-MM-dd HH:mm:ss"), title, message); + + file.write(data.toLocal8Bit()); + + file.close(); + } + + mutex.unlock(); +} diff --git a/HxLog.h b/HxLog.h new file mode 100644 index 0000000..c6d7f3f --- /dev/null +++ b/HxLog.h @@ -0,0 +1,15 @@ +#ifndef HXLOG_H +#define HXLOG_H + +#include + +class HxLog +{ +public: + static void append(QString title, QString message); + +private: + static QMutex mutex; +}; + +#endif // HXLOG_H diff --git a/HxProcess.cpp b/HxProcess.cpp new file mode 100644 index 0000000..d3dcd10 --- /dev/null +++ b/HxProcess.cpp @@ -0,0 +1,40 @@ +#include "HxProcess.h" + +//QString HxProcess::start(QString command) +//{ +// QString output; + +// auto process = new QProcess(); +// process->start("/bin/bash", QStringList() << "-c" << command); +// process->waitForFinished(); + +// output = QString(process->readAll()); + +// process->close(); + +// return output; +//} + + +QString HxProcess::start(QString command) +{ + QString output; + + auto array = command.split(" "); + + QString program = array.at(0); + QStringList arguments; + for (int i = 1; i < array.count(); i++) + arguments << array.at(i); + + QProcess process; + process.setProcessChannelMode(QProcess::MergedChannels); + process.start(program, arguments); + process.waitForFinished(); + + output = QString(process.readAll()); + + process.close(); + + return output; +} diff --git a/HxProcess.h b/HxProcess.h new file mode 100644 index 0000000..3944be3 --- /dev/null +++ b/HxProcess.h @@ -0,0 +1,19 @@ +#ifndef HXPROCESS_H +#define HXPROCESS_H + +#include +#include + +class HxProcess +{ +public: + /** + * @brief 同步启动进程 + * @param command 参数 + * @return + */ + static QString start(QString command); + +}; + +#endif // HXPROCESS_H diff --git a/HxSocket.cpp b/HxSocket.cpp new file mode 100644 index 0000000..5327ed6 --- /dev/null +++ b/HxSocket.cpp @@ -0,0 +1,93 @@ +#include "HxSocket.h" +#include "HxThread.h" + +#include + +HxSocket::HxSocket(quint16 port) +{ + connect(&server, &QTcpServer::newConnection, this, &HxSocket::new_connection); + server.listen(QHostAddress::Any, port); +} + +HxSocket::HxSocket(QString address, int port) +{ + is_reconnect = true; + + socket = new QTcpSocket(); + + connect(socket, &QTcpSocket::readyRead, this, &HxSocket::ready_read); + + connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::QueuedConnection); + + connect(this, &HxSocket::reconnection_event, this, &HxSocket::reconnection); + + /* 域名解析 */ + QHostInfo info = QHostInfo::fromName(address); + + this->port = port; + this->address = info.addresses().at(0).toString(); + + reconnection(); +} + +void HxSocket::new_connection() +{ + if (socket != nullptr) + socket->abort(); + + socket = server.nextPendingConnection(); + + connect(socket, &QTcpSocket::readyRead, this, &HxSocket::ready_read); + + connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()), Qt::QueuedConnection); +} + +void HxSocket::write(QByteArray data) +{ + if (socket == nullptr || socket->state() != QTcpSocket::ConnectedState) + return; + + data.append('\n'); + + socket->write(data); + socket->flush(); +} + +void HxSocket::ready_read() +{ + QByteArray msg = socket->readAll(); + + emit data_receive_event(msg.data()); +} + +void HxSocket::disconnected() +{ + if (is_reconnect) + emit reconnection_event(); +} + +void HxSocket::reconnection() +{ + /* 取消已有的连接 */ + if (socket != nullptr) + socket->disconnectFromHost(); + + /* 连接服务器 */ + socket->connectToHost(address, port); + + /* 等待连接 */ + if (!socket->waitForConnected(500)) + { + /* 使用 QThread::msleep 延时,会使 Socket 出现接收不到事件信息 (槽无法响应) */ + // auto time = QTime::currentTime().addMSecs(10000); + // while (QTime::currentTime() < time) + // { + // QCoreApplication::processEvents(QEventLoop::AllEvents, 100); + // QThread::msleep(100); + // } + + HxThread::sleep(10000); + + emit reconnection_event(); + } +} diff --git a/HxSocket.h b/HxSocket.h new file mode 100644 index 0000000..5fe5e74 --- /dev/null +++ b/HxSocket.h @@ -0,0 +1,41 @@ +#ifndef HXSOCKET_H +#define HXSOCKET_H + +#include +#include + +class HxSocket: public QObject +{ + Q_OBJECT +public: + HxSocket(quint16 port); + + HxSocket(QString address, int port); + +signals: + void data_receive_event(QByteArray data); + void reconnection_event(void); + +public slots: + void new_connection(); + + void write(QByteArray data); + + void ready_read(); + + void disconnected(); + + /** + * @brief 重连 + */ + void reconnection(); + +private: + int port; + QString address; + bool is_reconnect = false; + QTcpServer server; + QTcpSocket *socket = nullptr; +}; + +#endif // HXSOCKET_H diff --git a/HxSql.cpp b/HxSql.cpp new file mode 100644 index 0000000..01ae018 --- /dev/null +++ b/HxSql.cpp @@ -0,0 +1,38 @@ +#include "HxSql.h" +#include "HxTrace.h" + +#include +#include +#include +#include + +QSqlDatabase HxSql::open(QString filepath, QString connectionName) +{ + QSqlDatabase database; + if (QSqlDatabase::contains(connectionName)) + database = QSqlDatabase::database(connectionName); + else + database = QSqlDatabase::addDatabase("QSQLITE", connectionName); + + database.setDatabaseName(filepath); + + if (!database.open()) + { + QString bk_filepath = filepath + QString(".[%1].bk").arg(QDateTime::currentDateTime().toString("yyyyMMddHHmmss")); + + QFile::copy(filepath, bk_filepath); + + QFile::remove(filepath); + + HxTrace::debug_write_line("database", QString("file backup success. %1 => %2").arg(filepath).arg(bk_filepath)); + + database.open(); + } + + return database; +} + +void HxSql::close(QString connectionName) +{ + QSqlDatabase::removeDatabase(connectionName); +} diff --git a/HxSql.h b/HxSql.h new file mode 100644 index 0000000..3adfe2f --- /dev/null +++ b/HxSql.h @@ -0,0 +1,24 @@ +#ifndef HXSQL_H +#define HXSQL_H + +#include + +class HxSql +{ +public: + /** + * @brief 打开数据库 + * @param filepath 数据库文件路径 + * @param connectionName 连接名 + * @return QSqlDatabase 数据库对象 + */ + static QSqlDatabase open(QString filepath, QString connectionName); + + /** + * @brief 关闭数据库 + * @param connectionName 连接名 + */ + static void close(QString connectionName); +}; + +#endif // HXSQL_H diff --git a/HxSystem.cpp b/HxSystem.cpp new file mode 100644 index 0000000..9c60eaa --- /dev/null +++ b/HxSystem.cpp @@ -0,0 +1,218 @@ +#include "HxSystem.h" +#include "HxProcess.h" + +#include +#include + +static double m_memory_total = 0; +static double m_cpu_total = 0, m_cpu_use = 0; +static QMap> m_disk_rw_speed; + +QString HxSystem::get_cpu_model() +{ +#ifdef Q_OS_LINUX + return HxProcess::start("cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c").simplified().remove(0, 1); +#endif + +#ifdef Q_OS_WIN + QSettings *CPU = new QSettings("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", QSettings::NativeFormat); + return CPU->value("ProcessorNameString").toString(); +#endif + + return ""; +} + +int HxSystem::get_logical_cpu_number(){return HxProcess::start("cat /proc/cpuinfo| grep \"processor\"| wc -l").toInt();} + +bool HxSystem::get_cpu_temp(double *temp) +{ + Q_UNUSED(temp); + +#ifdef Q_OS_LINUX + auto result = HxProcess::start("cat /sys/class/thermal/thermal_zone0/temp"); + + auto data = result.simplified(); + + if(data.isNull()) + return false; + + *temp = data.toDouble() / 1000; + + return true; +#endif + + return false; +} + +bool HxSystem::get_cpu_status(double *cpu_rate) +{ + Q_UNUSED(cpu_rate); + Q_UNUSED(m_cpu_use); + Q_UNUSED(m_cpu_total); + +#ifdef Q_OS_LINUX + auto result = HxProcess::start("cat /proc/stat"); + + auto list = result.split("\n")[0].simplified().split(" "); + + if(list.size() > 3) + { + double use = list[1].toDouble() + list[2].toDouble() + list[3].toDouble(); + + double total = 0; + + for(int i = 1; i < list.size(); i++) + total += list[i].toDouble(); + + if(total - m_cpu_total > 0) + { + *cpu_rate = (use - m_cpu_use) / (total - m_cpu_total) * 100.0; + m_cpu_total = total; + m_cpu_use = use; + + return true; + } + } +#endif + + return false; +} + +bool HxSystem::get_memory_status(double *memory_use, double *memory_total, double *swap_use, double *swap_total) +{ + auto result = HxProcess::start("free -m"); + + auto list = result.split("\n"); + + if(list.size() >= 3) + { + auto memory_list = list[1].simplified().split(" "); + auto swap_list = list[2].simplified().split(" "); + + if(memory_list.size() >=7) + { + *memory_use = memory_list[2].toDouble(); + *memory_total = memory_list[1].toDouble(); + + m_memory_total = *memory_total; + } + + if(swap_list.size() >= 4) + { + *swap_use = swap_list[2].toDouble(); + *swap_total = swap_list[1].toDouble(); + } + + return true; + } + return false; +} + +bool HxSystem::get_program_status(double *cpu_usage, double *virtual_memory, double *resident_memory) +{ + auto result = HxProcess::start(QString("ps u %1").arg(getpid())); + + auto list = result.split("\n"); + + if(list.size() > 1) + { + auto info = list[1].simplified().split(" "); + + *cpu_usage = info[2].toDouble(); + + *virtual_memory = info[4].toDouble() / 1024 / 1024; + + *resident_memory = info[5].toDouble() / 1024; + + return true; + } + + return false; +} + +bool HxSystem::get_harddisk_status(QString disk, QString *file_system, QString *size, QString *use, double *read_speed, double *write_speed) +{ + auto result = HxProcess::start(QString("df -h %1").arg(disk)); + + auto list = result.split("\n"); + + if(list.size() > 1) + { + auto array = list[1].simplified().split(" "); + *file_system = array[0]; + *size = array[1]; + *use = array[4]; + + result = HxProcess::start(QString("iostat -k -d | grep %1").arg((*file_system).split("/").last())); + array = result.simplified().split(" "); + if(array.size() == 6) + { + if(m_disk_rw_speed.contains(*file_system)) + { + auto rw_speed = m_disk_rw_speed.value(*file_system); + + *read_speed = (array[4].toDouble() - rw_speed[0]); + *write_speed = (array[5].toDouble() - rw_speed[1]); + + rw_speed[0] = array[4].toDouble(); + rw_speed[1] = array[5].toDouble(); + + m_disk_rw_speed[*file_system] = rw_speed; + } + else + { + QList values; + values.append(array[4].toDouble()); + values.append(array[5].toDouble()); + m_disk_rw_speed.insert(*file_system, values); + } + } + + return true; + } + + return false; +} + +bool HxSystem::get_harddisk_temperature(QString file_system, QString *temperature) +{ + auto result = HxProcess::start(QString("echo tvis | sudo -S hddtemp '%1'").arg(file_system)); + + *temperature = result.simplified().split(":").last(); + + if((*temperature).isEmpty()) + return false; + + return true; +} + + +bool HxSystem::get_harddisk_smart(QString file_system, QString *smart) +{ + auto result = HxProcess::start(QString("echo tvis | sudo -S smartctl -i %1 | grep 'SMART support is'").arg(file_system)); + if(result.indexOf("Unavailable") != -1) + { + *smart = QObject::tr("不支持"); + } + else if(result.indexOf("Disabled") != -1) + { + *smart = QObject::tr("未启用"); + } + else if(result.indexOf("Available") != -1) + { + result = HxProcess::start(QString("echo tvis | sudo smartctl -H %1 | grep 'SMART overall-health self-assessment test result'").arg(file_system)); + if(result.indexOf("PASSED") != -1) + { + *smart = QObject::tr("良好"); + } + else + { + *smart = QObject::tr("故障"); + } + } + else + return false; + + return true; +} + diff --git a/HxSystem.h b/HxSystem.h new file mode 100644 index 0000000..338df95 --- /dev/null +++ b/HxSystem.h @@ -0,0 +1,84 @@ +#ifndef HXSYSTEM_H +#define HXSYSTEM_H + +#include + +class HxSystem +{ +public: + /** + * @brief 获取系统cpu型号 + * @return 系统cpu型号 + */ + static QString get_cpu_model(); + + /** + * @brief 获取系统逻辑CPU的个数 + * @return 系统逻辑CPU的个数 + */ + static int get_logical_cpu_number(); + + /** + * @brief 获取系统cpu温度 + * @param temp cpu温度 + * @return true: 成功; false 失败; + */ + static bool get_cpu_temp(double *temp); + + /** + * @brief 获取系统cpu状态 + * @param cpu_rate cpu使用率 + * @return true: 成功; false 失败; + */ + static bool get_cpu_status(double *cpu_rate); + + /** + * @brief 获取系统内存状态 + * @param memory_use 已用内存 + * @param memory_total 内存总大小 + * @param swap_use 已用交换空间 + * @param swap_total 交换空间总大小 + * @return true: 成功; false 失败; + */ + static bool get_memory_status(double *memory_use, double *memory_total, double *swap_use, double *swap_total); + + /** + * @brief 获取程序状态 + * @param cpu_usage CPU使用率 + * @param virtual_memory 虚拟内存使用量 + * @param resident_memory 物理内存使用量 + * @return true: 成功; false 失败; + */ + static bool get_program_status(double *cpu_usage, double *virtual_memory, double *resident_memory); + + /** + * @brief 获取硬盘状态 + * @param disk 路径 + * @param file_system 文件系统(磁盘路径) + * @param size 总大小 + * @param use 已用大小 + * @param read_speed 读速度 + * @param write_speed 写速度 + * @return true: 成功; false 失败; + */ + static bool get_harddisk_status(QString disk, QString *file_system, QString *size, QString *use, double *read_speed, double *write_speed); + + /** + * @brief 获取硬盘温度 + * @param file_system 文件系统(磁盘路径) + * @param temperature 温度 + * @return true: 成功; false 失败; + */ + static bool get_harddisk_temperature(QString file_system, QString *temperature); + + /** + * @brief 获取硬盘健康状态 + * @param file_system 文件系统(磁盘路径) + * @param smart 健康状态 + * @return true: 成功; false 失败; + */ + static bool get_harddisk_smart(QString file_system, QString *smart); + +}; + +#endif // HXSYSTEM_H diff --git a/HxTask.cpp b/HxTask.cpp new file mode 100644 index 0000000..9776178 --- /dev/null +++ b/HxTask.cpp @@ -0,0 +1,7 @@ +#include "HxTask.h" + +#include +#include + +QMutex HxTask::mutex; +QMap HxTask::dispatchers; diff --git a/HxTask.h b/HxTask.h new file mode 100644 index 0000000..c14b5e9 --- /dev/null +++ b/HxTask.h @@ -0,0 +1,191 @@ +#ifndef HXTASK_H +#define HXTASK_H + +#include "HxTrace.h" +//#include "HxThread.h" + +#include + +class HxTask +{ +public: + /** + * @brief 停止 + * @param uuid 任务唯一编码 + */ + static void stop(QUuid uuid) + { + if (dispatchers.contains(uuid)) + { + dispatchers[uuid] = false; + } + } + + /** + * @brief 异步执行 + * @param object 操作对象类 + * @param fn 操作对象类中的成员函数 + */ + template + static QFuture invoke(Functor functor) + { + return QtConcurrent::run(functor); + } + + /** + * @brief 异步执行 + * @param object 操作对象类 + * @param fn 操作对象类中的成员函数 + */ + template + static void run(Class *object, T (Class::*fn)()) + { + QtConcurrent::run( + [=](Class *_object, T (Class::*_fn)()) + { + (_object->*_fn)(); + }, + object, fn); + } + + /** + * @brief 异步执行线程 + * @param uuid 任务唯一编码 + * @param object 操作对象类 + * @param fn 操作对象类中的成员函数 + * @param millisecond 函数执行间隔频率,单位毫秒 + */ + template + static void run(QUuid uuid, Class *object, T (Class::*fn)(), int millisecond) + { + dispatchers.insert(uuid, true); + + QtConcurrent::run( + [=](QUuid _uuid, Class *_object, T (Class::*_fn)(), int _millisecond) + { + HxTrace::debug_write_line("HxTask", QString("Thread: %1, start").arg(_uuid.toString())); + + while (dispatchers[_uuid]) + { + (_object->*_fn)(); + + QThread::msleep(_millisecond); + } + + HxTrace::debug_write_line("HxTask", QString("Thread: %1, stop").arg(_uuid.toString())); + + dispatchers.remove(_uuid); + }, + uuid, object, fn, millisecond); + } + + /** + * @brief 任务并行 + * @param object 操作对象类 + * @param fn1 操作对象类中的成员函数1 + * @param millisecond1 函数1执行间隔频率,单位毫秒 + * @param fn2 操作对象类中的成员函数2 + * @param millisecond2 函数2执行间隔频率,单位毫秒 + * @return 任务唯一编码 + */ + template + static QUuid invoke(Class *object, T (Class::*fn1)(), int millisecond1, T (Class::*fn2)(), int millisecond2) + { + QUuid uuid = QUuid::createUuid(); + + HxTask::run(uuid, object, fn1, millisecond1); + HxTask::run(uuid, object, fn2, millisecond2); + + return uuid; + } + + /** + * @brief 任务并行 + * @param uuid 任务唯一编码 + * @param object 操作对象类 + * @param fn1 操作对象类中的成员函数1 + * @param millisecond1 函数1执行间隔频率,单位毫秒 + * @param fn2 操作对象类中的成员函数2 + * @param millisecond2 函数2执行间隔频率,单位毫秒 + * @return 任务唯一编码 + */ + template + static void invoke(QUuid uuid, Class *object, T (Class::*fn1)(), int millisecond1, T (Class::*fn2)(), int millisecond2) + { + HxTask::run(uuid, object, fn1, millisecond1); + HxTask::run(uuid, object, fn2, millisecond2); + } + + /** + * @brief 任务并行 + * @param object 操作对象类 + * @param fn1 操作对象类中的成员函数1 + * @param millisecond1 函数1执行间隔频率,单位毫秒 + * @param fn2 操作对象类中的成员函数2 + * @param millisecond2 函数2执行间隔频率,单位毫秒 + * @param fn3 操作对象类中的成员函数3 + * @param millisecond3 函数3执行间隔频率,单位毫秒 + * @return 任务唯一编码 + */ + template + static QUuid invoke(Class *object, T (Class::*fn1)(), int millisecond1, T (Class::*fn2)(), int millisecond2, T (Class::*fn3)(), int millisecond3) + { + QUuid uuid = QUuid::createUuid(); + + HxTask::run(uuid, object, fn1, millisecond1); + HxTask::run(uuid, object, fn2, millisecond2); + HxTask::run(uuid, object, fn3, millisecond3); + + return uuid; + } + + /** + * @brief 任务并行 + * @param uuid 任务唯一编码 + * @param object 操作对象类 + * @param fn1 操作对象类中的成员函数1 + * @param millisecond1 函数1执行间隔频率,单位毫秒 + * @param fn2 操作对象类中的成员函数2 + * @param millisecond2 函数2执行间隔频率,单位毫秒 + * @param fn3 操作对象类中的成员函数3 + * @param millisecond3 函数3执行间隔频率,单位毫秒 + * @return 任务唯一编码 + */ + template + static void invoke(QUuid uuid, Class *object, T (Class::*fn1)(), int millisecond1, T (Class::*fn2)(), int millisecond2, T (Class::*fn3)(), int millisecond3) + { + HxTask::run(uuid, object, fn1, millisecond1); + HxTask::run(uuid, object, fn2, millisecond2); + HxTask::run(uuid, object, fn3, millisecond3); + } + +private: + /** + * @brief mutex + */ + static QMutex mutex; + + /** + * @brief dispatchers + */ + static QMap dispatchers; +}; + +class HxParalle +{ +public: + /** + * @brief 任务并行 + * @param object 操作对象类 + * @param fn1 操作对象类中的成员函数1 + * @param fn2 操作对象类中的成员函数2 + */ + template + static void invoke(Class *object, T (Class::*fn1)(), T (Class::*fn2)()) + { + HxTask::run(object, fn1); + HxTask::run(object, fn2); + } +}; + +#endif // HXTASK_H diff --git a/HxThread.cpp b/HxThread.cpp new file mode 100644 index 0000000..6322405 --- /dev/null +++ b/HxThread.cpp @@ -0,0 +1,40 @@ +#include "HxThread.h" + +HxThread::HxThread(int millisecond) { m_wait_time = millisecond; } + +void HxThread::stop() +{ + m_thread_status = false; + + while (!m_stop_flags) + msleep(100); +} + +void HxThread::sleep(int millisecond) +{ + auto time = QTime::currentTime().addMSecs(millisecond); + while( QTime::currentTime() < time ) + QCoreApplication::processEvents(QEventLoop::AllEvents, 100); +} + +void HxThread::action() { } + +void HxThread::continue_with(){} + +void HxThread::run() +{ + m_stop_flags = false; + m_thread_status = true; + + while (m_thread_status) + { + action(); + + msleep(m_wait_time); + } + + /* Execution at completion */ + continue_with(); + + m_stop_flags = true; +} diff --git a/HxThread.h b/HxThread.h new file mode 100644 index 0000000..5b742a1 --- /dev/null +++ b/HxThread.h @@ -0,0 +1,60 @@ +#ifndef HXTHREAD_H +#define HXTHREAD_H + +#include +#include +#include + +class HxThread : public QThread +{ + Q_OBJECT +public: + /** + * @brief 线程类初始化 + * @param millisecond + */ + HxThread(int millisecond); + + /** + * @brief 停止 + */ + void stop(); + + static void sleep(int millisecond); + +protected: + /** + * @brief 线程任务 + */ + virtual void action(); + + /** + * @brief 线程任务结束后的处理任务 + */ + virtual void continue_with(); + + /** + * @brief 线程 + */ + virtual void run(); + +protected: + /** + * @brief 线程状态. true: 运行; false: 结束; + */ + bool m_thread_status = false; + +private: + /** + * @brief 线程轮询间隔, 单位毫秒 + * @ + */ + int m_wait_time; + + /** + * @brief 线程停止标志 + */ + bool m_stop_flags = true; +}; + +#endif // HXTHREAD_H diff --git a/HxTrace.cpp b/HxTrace.cpp new file mode 100644 index 0000000..20b6eda --- /dev/null +++ b/HxTrace.cpp @@ -0,0 +1,35 @@ +#include "HxTrace.h" + +#include + +void HxTrace::debug_write_line(QString title, QString message) +{ +#ifdef QT_DEBUG + qDebug("[%s] [%s] => %s", + qPrintable(QDateTime::currentDateTime().toString("yyyy/MM/dd HH:mm:ss")), + qPrintable(title), + qPrintable(message)); +#endif +} + +void HxTrace::debug_write_line(QString title, const char *format, ...) +{ +#ifdef QT_DEBUG + char output[1024]; + + va_list arg_list; + + va_start(arg_list, format); + +// vsprintf(output, format, arg_list); + + vsnprintf(output, 1024, format, arg_list); + + va_end(arg_list); + + qDebug("[%s] [%s] => %s", + qPrintable(QDateTime::currentDateTime().toString("yyyy/MM/dd HH:mm:ss")), + qPrintable(title), + output); +#endif +} diff --git a/HxTrace.h b/HxTrace.h new file mode 100644 index 0000000..7e6a5a3 --- /dev/null +++ b/HxTrace.h @@ -0,0 +1,24 @@ +#ifndef HXTRACE_H +#define HXTRACE_H + +#include + +class HxTrace +{ +public: + /** + * @brief 调试信息输出 + * @param title 标题 + * @param message 信息 + */ + static void debug_write_line(QString title, QString message); + + /** + * @brief 调试信息输出 + * @param title 标题 + * @param format 信息 + */ + static void debug_write_line(QString title, const char *format, ...); +}; + +#endif // HXTRACE_H diff --git a/HxUtils.pro b/HxUtils.pro new file mode 100644 index 0000000..92690c7 --- /dev/null +++ b/HxUtils.pro @@ -0,0 +1,57 @@ +QT -= gui +QT += concurrent +QT += sql +QT += network + +TEMPLATE = lib +CONFIG += staticlib +CONFIG += c++11 + +CONFIG += debug_and_release + +unix { + CONFIG(debug, debug|release){ + TARGET = debug/HxUtils + } else { + TARGET = release/HxUtils + } +} + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + HxDisk.cpp \ + HxLog.cpp \ + HxProcess.cpp \ + HxSocket.cpp \ + HxSql.cpp \ + HxSystem.cpp \ + HxTask.cpp \ + HxThread.cpp \ + HxTrace.cpp + +HEADERS += \ + HxDisk.h \ + HxLog.h \ + HxProcess.h \ + HxSocket.h \ + HxSql.h \ + HxSystem.h \ + HxThread.h \ + HxTask.h \ + HxTrace.h + +# Default rules for deployment. +unix { + target.path = $$[QT_INSTALL_PLUGINS]/generic +} +!isEmpty(target.path): INSTALLS += target