ThreadCompareItemManager.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. #include "ThreadCompareItemManager.h"
  2. #include "GlobalInfo.h"
  3. #include "SystemConfig.h"
  4. #include "CompareItemThread.h"
  5. #include "ThreadPool.h"
  6. #include "OneThread.h"
  7. /* 给对比项套一层壳,这个函数就是新的线程,在里面new出新的对比项实例,防止Qt报线程归属权错误
  8. 在函数中将对比项实例插入到线程管理器中 */
  9. void ThreadCompareItemManager::thread_compareItem(CalculateThreadInfo_t threadInfo)
  10. {
  11. auto pThread = new CompareItemThread(threadInfo);
  12. if(pThread == nullptr)
  13. {
  14. SPDLOG_ERROR("ThreadCompareItemManager: 创建对比项线程失败");
  15. return;
  16. }
  17. CompareItemManager.addCompareItemThread(pThread);
  18. /* 启动线程,就会一直阻塞在这里了 */
  19. pThread->threadTask();
  20. }
  21. ThreadCompareItemManager::ThreadCompareItemManager()
  22. {
  23. }
  24. ThreadCompareItemManager::~ThreadCompareItemManager()
  25. {
  26. }
  27. /* 线程函数 */
  28. void ThreadCompareItemManager::thread_CompareItemManager()
  29. {
  30. m_logger = spdlog::get("CompareItemManager");
  31. if(m_logger == nullptr)
  32. {
  33. fmt::print("ThreadCompareItemManager: CompareItemManager Logger not found.\n");
  34. return;
  35. }
  36. /* 初始化webapi */
  37. m_webAPIUrl = GInfo.webAPIUrl();
  38. m_webAPIID = GInfo.webAPIID();
  39. m_webAPIAppType = GInfo.webApiAppType();
  40. if(!m_fromWebAPI.initWebApi(m_webAPIUrl, m_webAPIID, m_webAPIAppType))
  41. {
  42. SPDLOG_LOGGER_ERROR(m_logger, "ThreadCompareItemManager: 初始化WebAPI失败");
  43. return;
  44. }
  45. /* 创建一些变量 */
  46. int threadSleepTime = 2; // 线程休眠时间,单位秒
  47. /* 获取基础配置,目前只获取一次 */
  48. updateBaseSettings();
  49. SPDLOG_LOGGER_INFO(m_logger, "开启对比项管理线程");
  50. while(true)
  51. {
  52. std::this_thread::sleep_for(std::chrono::seconds(threadSleepTime));
  53. if(threadSleepTime < 10)
  54. {
  55. /* 线程睡眠时间恢复为10秒 */
  56. threadSleepTime = 10;
  57. }
  58. /* ------------------------------------------------------------------
  59. * 处理对比项信息
  60. * ------------------------------------------------------------------ */
  61. processCompareItemInfo();
  62. /* ------------------------------ 更新检测时段 ------------------------------ */
  63. }
  64. SPDLOG_LOGGER_INFO(m_logger, "ThreadCompareItemManager: 线程结束");
  65. }
  66. /* 添加对比项实例 */
  67. void ThreadCompareItemManager::addCompareItemThread(CompareItemThread* pThread)
  68. {
  69. if(pThread == nullptr)
  70. {
  71. SPDLOG_LOGGER_ERROR(m_logger, "添加对比项线程失败,线程指针为空");
  72. return;
  73. }
  74. std::lock_guard<std::mutex> lock(m_mutexCompareItemThreads);
  75. int compareItemID = pThread->getThreadInfo().compareItemInfo.nID;
  76. if(m_mapThreads.contains(compareItemID))
  77. {
  78. SPDLOG_LOGGER_WARN(m_logger, "对比项线程已存在,ID: {}", compareItemID);
  79. return; // 对比项线程已存在
  80. }
  81. m_mapThreads.insert(compareItemID, pThread);
  82. SPDLOG_LOGGER_INFO(m_logger, "添加对比项线程成功,ID: {}", compareItemID);
  83. }
  84. /* 通过对比项ID和通道ID获取声卡通道信息 */
  85. SoundCardRoadInfo_t ThreadCompareItemManager::getSoundCardRoadInfo(int compareItemID, int roadNum)
  86. {
  87. std::lock_guard<std::mutex> lock(m_mutexCompareItemThreads);
  88. auto it = m_mapThreads.find(compareItemID);
  89. if(it == m_mapThreads.end())
  90. {
  91. SPDLOG_LOGGER_WARN(m_logger, "对比项线程不存在,ID: {}", compareItemID);
  92. return SoundCardRoadInfo_t();
  93. }
  94. auto compareInfo = it.value()->getThreadInfo().compareItemInfo;
  95. SoundCardRoadInfo_t roadInfo;
  96. for(const auto& road : compareInfo.mapRoad)
  97. {
  98. if(road.nCompareRoadNum == roadNum)
  99. {
  100. roadInfo = road.scRoadInfo;
  101. break;
  102. }
  103. }
  104. return roadInfo;
  105. }
  106. /* 更新基础设置信息,如数据库设置,噪音参数等 */
  107. bool ThreadCompareItemManager::updateBaseSettings()
  108. {
  109. /* 更新基础数据 */
  110. QMap<std::string, std::string> baseSettings;
  111. if(!m_fromWebAPI.getSystemConfig(baseSettings))
  112. {
  113. SPDLOG_LOGGER_ERROR(m_logger, "获取系统配置失败");
  114. return false;
  115. }
  116. /* 将获取到的配置转换成结构体 */
  117. SysConfig.parseConfigFromDatabase(baseSettings);
  118. /* 检测时段单独获取 */
  119. QMap<int, DetectPeriodConfig_t> mapDetectConfig;
  120. if(!m_fromWebAPI.getDetectPeriodConfig(mapDetectConfig))
  121. {
  122. SPDLOG_ERROR("获取对比项检测时段配置失败");
  123. return false;
  124. }
  125. SysConfig.setDetectPeriodConfig(mapDetectConfig);
  126. return true;
  127. }
  128. /* 对比项信息处理函数 */
  129. void ThreadCompareItemManager::processCompareItemInfo()
  130. {
  131. /* 获取对比项信息 */
  132. if(!m_fromWebAPI.getCompareItemInfo(m_listNewItems))
  133. {
  134. SPDLOG_LOGGER_DEBUG(m_logger, "ThreadCompareItemManager: 获取对比项失败");
  135. return;;
  136. }
  137. checkCompareItemInfo(m_listCreateItems, m_listUpdateItems, m_listDeleteItems);
  138. SPDLOG_LOGGER_DEBUG(m_logger, "要退出的对比项个数: {}, 要更新的对比项个数: {}, 要创建的对比项个数: {}",
  139. m_listDeleteItems.size(), m_listUpdateItems.size(), m_listCreateItems.size());
  140. /* 先删除已消失的对比项信息 */
  141. processDeleteCompareItemThreads(m_listDeleteItems);
  142. /* 更新需要更新的线程 */
  143. updateRunningThreads(m_listUpdateItems);
  144. /* 再创建新的对比项线程 */
  145. createNewCompareItemThreads(m_listCreateItems);
  146. }
  147. /**
  148. * @brief 处理对比项信息,新获取的和已有的对比
  149. *
  150. * @param createList 创建列表
  151. * @param updateList 更新列表,根据对比项ID进行更新信息
  152. * @param deleteList 删除列表
  153. */
  154. void ThreadCompareItemManager::checkCompareItemInfo(QList<CompareItemInfo_t>& createList, QList<CompareItemInfo_t>& updateList, QList<int>& deleteList)
  155. {
  156. createList.clear();
  157. updateList.clear();
  158. deleteList.clear();
  159. QMap<int, CompareItemInfo_t> mapNowItems;
  160. /* 先从对比项线程中获取对比项信息 */
  161. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end(); ++it)
  162. {
  163. BaseCalculateThread* pThread = it.value();
  164. if(pThread == nullptr)
  165. {
  166. continue;
  167. }
  168. /* 获取对比项信息 */
  169. CompareItemInfo_t itemInfo = pThread->getThreadInfo().compareItemInfo;
  170. mapNowItems.insert(itemInfo.nID, itemInfo);
  171. }
  172. /* 遍历新获取的对比项信息,找出需要新增的对比项和需要更新的对比项 */
  173. for(const CompareItemInfo_t& item : m_listNewItems)
  174. {
  175. if(!mapNowItems.contains(item.nID))
  176. {
  177. /* 新对比项,添加到创建列表 */
  178. createList.append(item);
  179. } else
  180. {
  181. /* 已有对比项,检查是否需要更新 */
  182. const CompareItemInfo_t& existingItem = mapNowItems.value(item.nID);
  183. /* 先对比基础信息 */
  184. if(!existingItem.isEqualBase(item))
  185. {
  186. /* 基础信息不同,需要更新 */
  187. updateList.append(item);
  188. continue;
  189. }
  190. /* 在对比对比项通道信息 */
  191. if(!existingItem.isEqualRoads(item))
  192. {
  193. /* 通道信息不同,需要更新 */
  194. updateList.append(item);
  195. continue;
  196. }
  197. }
  198. }
  199. /* 遍历当前对比项信息,找出需要删除的对比项 */
  200. for(auto it : mapNowItems)
  201. {
  202. bool isFound = false;
  203. for(const CompareItemInfo_t& newItem : m_listNewItems)
  204. {
  205. if(it.nID == newItem.nID)
  206. {
  207. isFound = true;
  208. break; // 找到对应的对比项,不需要删除
  209. }
  210. }
  211. if(!isFound)
  212. {
  213. /* 当前对比项不在新获取的对比项中,说明需要删除 */
  214. deleteList.append(it.nID);
  215. }
  216. }
  217. }
  218. /**
  219. * @brief 处理需要删除的对比项线程
  220. * 1、先处理已经停止的线程
  221. * 2、再将这次列表中的对比项ID对应的线程设置为停止状态,待到下次循环再删除已经停止完成的线程
  222. *
  223. * @param deleteList
  224. */
  225. void ThreadCompareItemManager::processDeleteCompareItemThreads(const QList<int>& deleteList)
  226. {
  227. /* 先处理已经停止运行的线程 */
  228. for(auto it = m_mapThreads.begin(); it != m_mapThreads.end();)
  229. {
  230. BaseCalculateThread* pThread = it.value();
  231. if(pThread == nullptr)
  232. {
  233. SPDLOG_LOGGER_WARN(m_logger, "对比项线程指针为空,即将删除该线程指针");
  234. it = m_mapThreads.erase(it);
  235. continue;
  236. }
  237. if(pThread->getThreadInfo().threadState == EThreadState::State_Stopped)
  238. {
  239. /* 线程已经停止,直接删除 */
  240. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 已经停止,准备删除", pThread->getThreadInfo().compareItemInfo.strName.toStdString());
  241. delete pThread;
  242. it = m_mapThreads.erase(it);
  243. continue;
  244. }
  245. ++it;
  246. }
  247. /* 停止本次需要停止的线程 */
  248. for(auto it : m_mapThreads)
  249. {
  250. int compareItemID = it->getThreadInfo().compareItemInfo.nID;
  251. if(deleteList.contains(compareItemID))
  252. {
  253. /* 设置线程停止标志 */
  254. it->stopThread();
  255. SPDLOG_LOGGER_INFO(m_logger, "对比项线程 {} 设置为停止状态", it->getThreadInfo().compareItemInfo.strName.toStdString());
  256. }
  257. }
  258. }
  259. /* 更新正在运行的线程信息 */
  260. void ThreadCompareItemManager::updateRunningThreads(const QList<CompareItemInfo_t>& updateList)
  261. {
  262. if(updateList.isEmpty())
  263. {
  264. return;
  265. }
  266. for(const CompareItemInfo_t& item : updateList)
  267. {
  268. auto it = m_mapThreads.find(item.nID);
  269. if(it == m_mapThreads.end())
  270. {
  271. SPDLOG_LOGGER_WARN(m_logger, "对比项线程 {} 不存在,无法更新信息", item.strName.toStdString());
  272. continue;
  273. }
  274. BaseCalculateThread* pThread = it.value();
  275. if(pThread == nullptr)
  276. {
  277. continue;
  278. }
  279. CalculateThreadInfo_t threadInfo;
  280. threadInfo.compareItemInfo = item;
  281. pThread->updateThreadInfo(threadInfo);
  282. }
  283. }
  284. /* 创建新的线程 */
  285. bool ThreadCompareItemManager::createNewCompareItemThreads(const QList<CompareItemInfo_t>& createList)
  286. {
  287. if(createList.isEmpty())
  288. {
  289. SPDLOG_LOGGER_DEBUG(m_logger, "没有新的对比项需要创建");
  290. return true;
  291. }
  292. for(auto& it : createList)
  293. {
  294. /* 创建新的对比项线程 */
  295. CalculateThreadInfo_t threadInfo;
  296. threadInfo.compareItemInfo = it;
  297. threadInfo.threadType = EThreadType::Type_CompareItem;
  298. threadInfo.threadState = EThreadState::State_Inited;
  299. CPPTP.add_task(&ThreadCompareItemManager::thread_compareItem, threadInfo);
  300. /* 创建线程对象 */
  301. // CompareItemThread* pThread = new CompareItemThread(threadInfo);
  302. // if(pThread == nullptr)
  303. // {
  304. // SPDLOG_LOGGER_ERROR(m_logger, "创建对比项线程 {} 失败", it.strName.toStdString());
  305. // return false;
  306. // }
  307. /* 启动线程 */
  308. // CPPTP.add_task(&CompareItemThread::threadTask, pThread);
  309. /* 添加到线程列表中 */
  310. // m_mapThreads.insert(it.nID, pThread);
  311. }
  312. return true;
  313. }
  314. /* 处理检测时段信息 */
  315. void ThreadCompareItemManager::processDetectPeriodInfo()
  316. {
  317. /* 获取计划信息 */
  318. QMap<int, DetectPeriodConfig_t> mapNewDetectConfig;
  319. if(!m_fromWebAPI.getDetectPeriodConfig(mapNewDetectConfig))
  320. {
  321. SPDLOG_LOGGER_ERROR(m_logger, "获取检测时段配置失败");
  322. return;
  323. }
  324. QMap<int, DetectPeriodConfig_t> mapUpdateDetectConfig;
  325. checkDetectPeriodInfo(mapNewDetectConfig, mapUpdateDetectConfig);
  326. }
  327. /* 检查获取出更新的对比项信息 */
  328. void ThreadCompareItemManager::checkDetectPeriodInfo(QMap<int, DetectPeriodConfig_t> newDetectInfo, QMap<int, DetectPeriodConfig_t>& updateList)
  329. {
  330. for(const auto& it : newDetectInfo)
  331. {
  332. int compareItemID = it.nID;
  333. for(const auto& existingItem : m_mapDetectPeriod)
  334. {
  335. if(existingItem.nID == compareItemID)
  336. {
  337. /* 已经存在的对比项,检查是否需要更新 */
  338. if(existingItem == it)
  339. {
  340. /* 对比项信息相同,不需要更新 */
  341. continue;
  342. } else
  343. {
  344. /* 对比项信息不同,需要更新 */
  345. updateList.insert(compareItemID, it);
  346. }
  347. return;
  348. }
  349. }
  350. }
  351. }