mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 01:20:06 +00:00 
			
		
		
		
	Merge pull request #230 from dpaulat/feature/thread-error-handling
Catch exceptions in background threads
This commit is contained in:
		
						commit
						a47c77e4a2
					
				
					 13 changed files with 866 additions and 665 deletions
				
			
		|  | @ -611,6 +611,8 @@ void MainWindow::on_actionCheckForUpdates_triggered() | |||
|    boost::asio::post( | ||||
|       p->threadPool_, | ||||
|       [this]() | ||||
|       { | ||||
|          try | ||||
|          { | ||||
|             if (!p->updateManager_->CheckForUpdates(main::kVersionString_)) | ||||
|             { | ||||
|  | @ -627,6 +629,11 @@ void MainWindow::on_actionCheckForUpdates_triggered() | |||
|                      messageBox->show(); | ||||
|                   }); | ||||
|             } | ||||
|          } | ||||
|          catch (const std::exception& ex) | ||||
|          { | ||||
|             logger_->error(ex.what()); | ||||
|          } | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
|  | @ -662,10 +669,17 @@ void MainWindowImpl::AsyncSetup() | |||
|    { | ||||
|       boost::asio::post(threadPool_, | ||||
|                         [this]() | ||||
|                         { | ||||
|                            try | ||||
|                            { | ||||
|                               manager::UpdateManager::RemoveTemporaryReleases(); | ||||
|                               updateManager_->CheckForUpdates( | ||||
|                                  main::kVersionString_); | ||||
|                            } | ||||
|                            catch (const std::exception& ex) | ||||
|                            { | ||||
|                               logger_->error(ex.what()); | ||||
|                            } | ||||
|                         }); | ||||
|    } | ||||
| } | ||||
|  |  | |||
|  | @ -42,7 +42,17 @@ public: | |||
|          [this](const types::TextEventKey& key, size_t messageIndex) | ||||
|          { | ||||
|             boost::asio::post(threadPool_, | ||||
|                               [=, this]() { HandleAlert(key, messageIndex); }); | ||||
|                               [=, this]() | ||||
|                               { | ||||
|                                  try | ||||
|                                  { | ||||
|                                     HandleAlert(key, messageIndex); | ||||
|                                  } | ||||
|                                  catch (const std::exception& ex) | ||||
|                                  { | ||||
|                                     logger_->error(ex.what()); | ||||
|                                  } | ||||
|                               }); | ||||
|          }); | ||||
|    } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,6 +25,8 @@ public: | |||
| 
 | ||||
|    ~Impl() { threadPool_.join(); } | ||||
| 
 | ||||
|    void DownloadSync(const std::shared_ptr<request::DownloadRequest>& request); | ||||
| 
 | ||||
|    boost::asio::thread_pool threadPool_ {1u}; | ||||
| 
 | ||||
|    DownloadManager* self_; | ||||
|  | @ -36,13 +38,25 @@ DownloadManager::~DownloadManager() = default; | |||
| void DownloadManager::Download( | ||||
|    const std::shared_ptr<request::DownloadRequest>& request) | ||||
| { | ||||
|    boost::asio::post( | ||||
|       p->threadPool_, | ||||
|    boost::asio::post(p->threadPool_, | ||||
|                      [=]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            p->DownloadSync(request); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void DownloadManager::Impl::DownloadSync( | ||||
|    const std::shared_ptr<request::DownloadRequest>& request) | ||||
| { | ||||
|    // Prepare destination file
 | ||||
|          const std::filesystem::path& destinationPath = | ||||
|             request->destination_path(); | ||||
|    const std::filesystem::path& destinationPath = request->destination_path(); | ||||
| 
 | ||||
|    if (!destinationPath.has_parent_path()) | ||||
|    { | ||||
|  | @ -95,8 +109,7 @@ void DownloadManager::Download( | |||
|                          std::ios_base::trunc}; | ||||
|    if (!ofs.is_open() || !ofs.good()) | ||||
|    { | ||||
|             logger_->error( | ||||
|                "Unable to open destination file for writing: \"{}\"", | ||||
|       logger_->error("Unable to open destination file for writing: \"{}\"", | ||||
|                      destinationPath.string()); | ||||
| 
 | ||||
|       Q_EMIT request->RequestComplete( | ||||
|  | @ -110,8 +123,8 @@ void DownloadManager::Download( | |||
|    cpr::cpr_off_t                        lastDownloadTotal {}; | ||||
| 
 | ||||
|    // Download file
 | ||||
|          cpr::Response response = | ||||
|             cpr::Get(cpr::Url {request->url()}, | ||||
|    cpr::Response response = cpr::Get( | ||||
|       cpr::Url {request->url()}, | ||||
|       cpr::ProgressCallback( | ||||
|          [&](cpr::cpr_off_t downloadTotal, | ||||
|              cpr::cpr_off_t downloadNow, | ||||
|  | @ -125,17 +138,14 @@ void DownloadManager::Download( | |||
|                std::chrono::system_clock::now(); | ||||
| 
 | ||||
|             // Only emit an update every 100ms
 | ||||
|                            if ((now > lastUpdated + 100ms || | ||||
|                                 downloadNow == downloadTotal) && | ||||
|             if ((now > lastUpdated + 100ms || downloadNow == downloadTotal) && | ||||
|                 (downloadNow != lastDownloadNow || | ||||
|                  downloadTotal != lastDownloadTotal)) | ||||
|             { | ||||
|                               logger_->trace("Downloaded: {} / {}", | ||||
|                                              downloadNow, | ||||
|                                              downloadTotal); | ||||
|                logger_->trace( | ||||
|                   "Downloaded: {} / {}", downloadNow, downloadTotal); | ||||
| 
 | ||||
|                               Q_EMIT request->ProgressUpdated(downloadNow, | ||||
|                                                               downloadTotal); | ||||
|                Q_EMIT request->ProgressUpdated(downloadNow, downloadTotal); | ||||
| 
 | ||||
|                lastUpdated       = now; | ||||
|                lastDownloadNow   = downloadNow; | ||||
|  | @ -156,8 +166,8 @@ void DownloadManager::Download( | |||
|    ofs.close(); | ||||
| 
 | ||||
|    // Handle error response
 | ||||
|          if (response.error.code != cpr::ErrorCode::OK || | ||||
|              request->IsCanceled() || !ofsGood) | ||||
|    if (response.error.code != cpr::ErrorCode::OK || request->IsCanceled() || | ||||
|        !ofsGood) | ||||
|    { | ||||
|       request::DownloadRequest::CompleteReason reason = | ||||
|          request::DownloadRequest::CompleteReason::IOError; | ||||
|  | @ -198,8 +208,7 @@ void DownloadManager::Download( | |||
| 
 | ||||
|    // Handle response
 | ||||
|    const auto contentMd5 = response.header.find("content-md5"); | ||||
|          if (contentMd5 != response.header.cend() && | ||||
|              !contentMd5->second.empty()) | ||||
|    if (contentMd5 != response.header.cend() && !contentMd5->second.empty()) | ||||
|    { | ||||
|       // Open file for reading
 | ||||
|       std::ifstream is {destinationPath, | ||||
|  | @ -219,8 +228,7 @@ void DownloadManager::Download( | |||
|       std::vector<std::uint8_t> digest {}; | ||||
|       if (!util::ComputeDigest(EVP_md5(), is, digest)) | ||||
|       { | ||||
|                logger_->error("Failed to compute MD5: {}", | ||||
|                               destinationPath.string()); | ||||
|          logger_->error("Failed to compute MD5: {}", destinationPath.string()); | ||||
| 
 | ||||
|          Q_EMIT request->RequestComplete( | ||||
|             request::DownloadRequest::CompleteReason::IOError); | ||||
|  | @ -231,13 +239,13 @@ void DownloadManager::Download( | |||
|       // Compare calculated MD5 with digest in response header
 | ||||
|       QByteArray expectedDigestArray = | ||||
|          QByteArray::fromBase64(contentMd5->second.c_str()); | ||||
|             std::vector<std::uint8_t> expectedDigest( | ||||
|                expectedDigestArray.cbegin(), expectedDigestArray.cend()); | ||||
|       std::vector<std::uint8_t> expectedDigest(expectedDigestArray.cbegin(), | ||||
|                                                expectedDigestArray.cend()); | ||||
| 
 | ||||
|       if (digest != expectedDigest) | ||||
|       { | ||||
|                QByteArray calculatedDigest( | ||||
|                   reinterpret_cast<char*>(digest.data()), digest.size()); | ||||
|          QByteArray calculatedDigest(reinterpret_cast<char*>(digest.data()), | ||||
|                                      digest.size()); | ||||
| 
 | ||||
|          logger_->error("Digest mismatch: {} != {}", | ||||
|                         calculatedDigest.toBase64().toStdString(), | ||||
|  | @ -253,7 +261,6 @@ void DownloadManager::Download( | |||
|    logger_->info("Download complete: {}", request->url()); | ||||
|    Q_EMIT request->RequestComplete( | ||||
|       request::DownloadRequest::CompleteReason::OK); | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<DownloadManager> DownloadManager::Instance() | ||||
|  |  | |||
|  | @ -156,6 +156,8 @@ PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) | |||
| { | ||||
|    boost::asio::post(p->threadPool_, | ||||
|                      [this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            p->InitializePlacefileSettings(); | ||||
| 
 | ||||
|  | @ -163,6 +165,11 @@ PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) | |||
|                            main::Application::WaitForInitialization(); | ||||
|                            p->ReadPlacefileSettings(); | ||||
|                            Q_EMIT PlacefilesInitialized(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
|  | @ -678,7 +685,7 @@ void PlacefileManager::Impl::PlacefileRecord::ScheduleRefresh() | |||
|          } | ||||
|          else | ||||
|          { | ||||
|             Update(); | ||||
|             UpdateAsync(); | ||||
|          } | ||||
|       }); | ||||
| } | ||||
|  | @ -691,7 +698,18 @@ void PlacefileManager::Impl::PlacefileRecord::CancelRefresh() | |||
| 
 | ||||
| void PlacefileManager::Impl::PlacefileRecord::UpdateAsync() | ||||
| { | ||||
|    boost::asio::post(threadPool_, [this]() { Update(); }); | ||||
|    boost::asio::post(threadPool_, | ||||
|                      [this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            Update(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<PlacefileManager> PlacefileManager::Instance() | ||||
|  |  | |||
|  | @ -196,6 +196,7 @@ public: | |||
|                       std::shared_ptr<ProviderManager> providerManager, | ||||
|                       bool                             enabled); | ||||
|    void RefreshData(std::shared_ptr<ProviderManager> providerManager); | ||||
|    void RefreshDataSync(std::shared_ptr<ProviderManager> providerManager); | ||||
| 
 | ||||
|    std::tuple<std::shared_ptr<types::RadarProductRecord>, | ||||
|               std::chrono::system_clock::time_point> | ||||
|  | @ -225,6 +226,8 @@ public: | |||
|    void PopulateLevel3ProductTimes(const std::string& product, | ||||
|                                    std::chrono::system_clock::time_point time); | ||||
| 
 | ||||
|    void UpdateAvailableProductsSync(); | ||||
| 
 | ||||
|    static void | ||||
|    PopulateProductTimes(std::shared_ptr<ProviderManager> providerManager, | ||||
|                         RadarProductRecordMap&           productRecordMap, | ||||
|  | @ -575,6 +578,8 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group, | |||
|       boost::asio::post( | ||||
|          p->threadPool_, | ||||
|          [=, this]() | ||||
|          { | ||||
|             try | ||||
|             { | ||||
|                providerManager->provider_->RequestAvailableProducts(); | ||||
|                auto availableProducts = | ||||
|  | @ -587,6 +592,11 @@ void RadarProductManager::EnableRefresh(common::RadarProductGroup group, | |||
|                { | ||||
|                   p->EnableRefresh(uuid, providerManager, enabled); | ||||
|                } | ||||
|             } | ||||
|             catch (const std::exception& ex) | ||||
|             { | ||||
|                logger_->error(ex.what()); | ||||
|             } | ||||
|          }); | ||||
|    } | ||||
| } | ||||
|  | @ -664,27 +674,37 @@ void RadarProductManagerImpl::RefreshData( | |||
|       providerManager->refreshTimer_.cancel(); | ||||
|    } | ||||
| 
 | ||||
|    boost::asio::post( | ||||
|       threadPool_, | ||||
|    boost::asio::post(threadPool_, | ||||
|                      [=, this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            RefreshDataSync(providerManager); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void RadarProductManagerImpl::RefreshDataSync( | ||||
|    std::shared_ptr<ProviderManager> providerManager) | ||||
| { | ||||
|    using namespace std::chrono_literals; | ||||
| 
 | ||||
|          auto [newObjects, totalObjects] = | ||||
|             providerManager->provider_->Refresh(); | ||||
|    auto [newObjects, totalObjects] = providerManager->provider_->Refresh(); | ||||
| 
 | ||||
|    std::chrono::milliseconds interval = kFastRetryInterval_; | ||||
| 
 | ||||
|    if (totalObjects > 0) | ||||
|    { | ||||
|       std::string key = providerManager->provider_->FindLatestKey(); | ||||
|             auto        latestTime = | ||||
|                providerManager->provider_->GetTimePointByKey(key); | ||||
|       auto latestTime = providerManager->provider_->GetTimePointByKey(key); | ||||
| 
 | ||||
|       auto updatePeriod      = providerManager->provider_->update_period(); | ||||
|       auto lastModified      = providerManager->provider_->last_modified(); | ||||
|             auto sinceLastModified = | ||||
|                std::chrono::system_clock::now() - lastModified; | ||||
|       auto sinceLastModified = std::chrono::system_clock::now() - lastModified; | ||||
| 
 | ||||
|       // For the default interval, assume products are updated at a
 | ||||
|       // constant rate. Expect the next product at a time based on the
 | ||||
|  | @ -707,9 +727,7 @@ void RadarProductManagerImpl::RefreshData( | |||
|       if (newObjects > 0) | ||||
|       { | ||||
|          Q_EMIT providerManager->NewDataAvailable( | ||||
|                   providerManager->group_, | ||||
|                   providerManager->product_, | ||||
|                   latestTime); | ||||
|             providerManager->group_, providerManager->product_, latestTime); | ||||
|       } | ||||
|    } | ||||
|    else if (providerManager->refreshEnabled_) | ||||
|  | @ -752,7 +770,6 @@ void RadarProductManagerImpl::RefreshData( | |||
|             }); | ||||
|       } | ||||
|    } | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
| std::set<std::chrono::system_clock::time_point> | ||||
|  | @ -1009,7 +1026,16 @@ void RadarProductManagerImpl::LoadNexradFileAsync( | |||
| { | ||||
|    boost::asio::post(threadPool_, | ||||
|                      [=, &mutex]() | ||||
|                      { LoadNexradFile(load, request, mutex, time); }); | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            LoadNexradFile(load, request, mutex, time); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void RadarProductManagerImpl::LoadNexradFile( | ||||
|  | @ -1441,31 +1467,41 @@ void RadarProductManager::UpdateAvailableProducts() | |||
| 
 | ||||
|    logger_->debug("UpdateAvailableProducts()"); | ||||
| 
 | ||||
|    boost::asio::post( | ||||
|       p->threadPool_, | ||||
|    boost::asio::post(p->threadPool_, | ||||
|                      [this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            p->UpdateAvailableProductsSync(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void RadarProductManagerImpl::UpdateAvailableProductsSync() | ||||
| { | ||||
|    auto level3ProviderManager = | ||||
|             p->GetLevel3ProviderManager(kDefaultLevel3Product_); | ||||
|       GetLevel3ProviderManager(kDefaultLevel3Product_); | ||||
|    level3ProviderManager->provider_->RequestAvailableProducts(); | ||||
|    auto updatedAwipsIdList = | ||||
|       level3ProviderManager->provider_->GetAvailableProducts(); | ||||
| 
 | ||||
|          std::unique_lock lock {p->availableCategoryMutex_}; | ||||
|    std::unique_lock lock {availableCategoryMutex_}; | ||||
| 
 | ||||
|    for (common::Level3ProductCategory category : | ||||
|         common::Level3ProductCategoryIterator()) | ||||
|    { | ||||
|             const auto& products = | ||||
|                common::GetLevel3ProductsByCategory(category); | ||||
|       const auto& products = common::GetLevel3ProductsByCategory(category); | ||||
| 
 | ||||
|       std::unordered_map<std::string, std::vector<std::string>> | ||||
|          availableProducts; | ||||
| 
 | ||||
|       for (const auto& product : products) | ||||
|       { | ||||
|                const auto& awipsIds = | ||||
|                   common::GetLevel3AwipsIdsByProduct(product); | ||||
|          const auto& awipsIds = common::GetLevel3AwipsIdsByProduct(product); | ||||
| 
 | ||||
|          std::vector<std::string> availableAwipsIds; | ||||
| 
 | ||||
|  | @ -1481,24 +1517,23 @@ void RadarProductManager::UpdateAvailableProducts() | |||
| 
 | ||||
|          if (!availableAwipsIds.empty()) | ||||
|          { | ||||
|                   availableProducts.insert_or_assign( | ||||
|                      product, std::move(availableAwipsIds)); | ||||
|             availableProducts.insert_or_assign(product, | ||||
|                                                std::move(availableAwipsIds)); | ||||
|          } | ||||
|       } | ||||
| 
 | ||||
|       if (!availableProducts.empty()) | ||||
|       { | ||||
|                p->availableCategoryMap_.insert_or_assign( | ||||
|                   category, std::move(availableProducts)); | ||||
|          availableCategoryMap_.insert_or_assign(category, | ||||
|                                                 std::move(availableProducts)); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|                p->availableCategoryMap_.erase(category); | ||||
|          availableCategoryMap_.erase(category); | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
|          Q_EMIT Level3ProductsChanged(); | ||||
|       }); | ||||
|    Q_EMIT self_->Level3ProductsChanged(); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<RadarProductManager> | ||||
|  |  | |||
|  | @ -49,10 +49,17 @@ public: | |||
| 
 | ||||
|       boost::asio::post(threadPool_, | ||||
|                         [this]() | ||||
|                         { | ||||
|                            try | ||||
|                            { | ||||
|                               main::Application::WaitForInitialization(); | ||||
|                               logger_->debug("Start Refresh"); | ||||
|                               Refresh(); | ||||
|                            } | ||||
|                            catch (const std::exception& ex) | ||||
|                            { | ||||
|                               logger_->error(ex.what()); | ||||
|                            } | ||||
|                         }); | ||||
|    } | ||||
| 
 | ||||
|  | @ -70,6 +77,7 @@ public: | |||
|    } | ||||
| 
 | ||||
|    void HandleMessage(std::shared_ptr<awips::TextProductMessage> message); | ||||
|    void RefreshAsync(); | ||||
|    void Refresh(); | ||||
| 
 | ||||
|    boost::asio::thread_pool threadPool_ {1u}; | ||||
|  | @ -130,6 +138,8 @@ void TextEventManager::LoadFile(const std::string& filename) | |||
| 
 | ||||
|    boost::asio::post(p->threadPool_, | ||||
|                      [=, this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            awips::TextProductFile file; | ||||
| 
 | ||||
|  | @ -146,6 +156,11 @@ void TextEventManager::LoadFile(const std::string& filename) | |||
|                            { | ||||
|                               p->HandleMessage(message); | ||||
|                            } | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
|  | @ -212,6 +227,22 @@ void TextEventManager::Impl::HandleMessage( | |||
|    } | ||||
| } | ||||
| 
 | ||||
| void TextEventManager::Impl::RefreshAsync() | ||||
| { | ||||
|    boost::asio::post(threadPool_, | ||||
|                      [this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            Refresh(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void TextEventManager::Impl::Refresh() | ||||
| { | ||||
|    logger_->trace("Refresh"); | ||||
|  | @ -257,7 +288,7 @@ void TextEventManager::Impl::Refresh() | |||
|          } | ||||
|          else | ||||
|          { | ||||
|             Refresh(); | ||||
|             RefreshAsync(); | ||||
|          } | ||||
|       }); | ||||
| } | ||||
|  |  | |||
|  | @ -69,11 +69,13 @@ public: | |||
| 
 | ||||
|    void Pause(); | ||||
|    void Play(); | ||||
|    void PlaySync(); | ||||
|    void | ||||
|    SelectTimeAsync(std::chrono::system_clock::time_point selectedTime = {}); | ||||
|    std::pair<bool, bool> | ||||
|         SelectTime(std::chrono::system_clock::time_point selectedTime = {}); | ||||
|    void StepAsync(Direction direction); | ||||
|    void Step(Direction direction); | ||||
| 
 | ||||
|    boost::asio::thread_pool playThreadPool_ {1}; | ||||
|    boost::asio::thread_pool selectThreadPool_ {1}; | ||||
|  | @ -405,8 +407,6 @@ void TimelineManager::Impl::UpdateCacheLimit( | |||
| 
 | ||||
| void TimelineManager::Impl::Play() | ||||
| { | ||||
|    using namespace std::chrono_literals; | ||||
| 
 | ||||
|    if (animationState_ != types::AnimationState::Play) | ||||
|    { | ||||
|       animationState_ = types::AnimationState::Play; | ||||
|  | @ -418,10 +418,24 @@ void TimelineManager::Impl::Play() | |||
|       animationTimer_.cancel(); | ||||
|    } | ||||
| 
 | ||||
|    boost::asio::post( | ||||
|       playThreadPool_, | ||||
|    boost::asio::post(playThreadPool_, | ||||
|                      [this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            PlaySync(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void TimelineManager::Impl::PlaySync() | ||||
| { | ||||
|    using namespace std::chrono_literals; | ||||
| 
 | ||||
|    // Take a lock for time selection
 | ||||
|    std::unique_lock lock {selectTimeMutex_}; | ||||
| 
 | ||||
|  | @ -504,14 +518,23 @@ void TimelineManager::Impl::Play() | |||
|             logger_->warn("Play timer error: {}", e.message()); | ||||
|          } | ||||
|       }); | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
| void TimelineManager::Impl::SelectTimeAsync( | ||||
|    std::chrono::system_clock::time_point selectedTime) | ||||
| { | ||||
|    boost::asio::post(selectThreadPool_, | ||||
|                      [=, this]() { SelectTime(selectedTime); }); | ||||
|                      [=, this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            SelectTime(selectedTime); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| std::pair<bool, bool> TimelineManager::Impl::SelectTime( | ||||
|  | @ -597,9 +620,21 @@ std::pair<bool, bool> TimelineManager::Impl::SelectTime( | |||
| 
 | ||||
| void TimelineManager::Impl::StepAsync(Direction direction) | ||||
| { | ||||
|    boost::asio::post( | ||||
|       selectThreadPool_, | ||||
|    boost::asio::post(selectThreadPool_, | ||||
|                      [=, this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            Step(direction); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void TimelineManager::Impl::Step(Direction direction) | ||||
| { | ||||
|    // Take a lock for time selection
 | ||||
|    std::unique_lock lock {selectTimeMutex_}; | ||||
|  | @ -614,8 +649,7 @@ void TimelineManager::Impl::StepAsync(Direction direction) | |||
|    // Request active volume times
 | ||||
|    auto radarProductManager = | ||||
|       manager::RadarProductManager::Instance(radarSite_); | ||||
|          auto volumeTimes = | ||||
|             radarProductManager->GetActiveVolumeTimes(queryTime); | ||||
|    auto volumeTimes = radarProductManager->GetActiveVolumeTimes(queryTime); | ||||
| 
 | ||||
|    if (volumeTimes.empty()) | ||||
|    { | ||||
|  | @ -636,8 +670,7 @@ void TimelineManager::Impl::StepAsync(Direction direction) | |||
|    else | ||||
|    { | ||||
|       // Get the current element in the set
 | ||||
|             it = scwx::util::GetBoundedElementIterator(volumeTimes, | ||||
|                                                        adjustedTime_); | ||||
|       it = scwx::util::GetBoundedElementIterator(volumeTimes, adjustedTime_); | ||||
|    } | ||||
| 
 | ||||
|    if (it == volumeTimes.cend()) | ||||
|  | @ -681,7 +714,6 @@ void TimelineManager::Impl::StepAsync(Direction direction) | |||
|          Q_EMIT self_->SelectedTimeUpdated(adjustedTime_); | ||||
|       } | ||||
|    } | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<TimelineManager> TimelineManager::Instance() | ||||
|  |  | |||
|  | @ -325,9 +325,16 @@ void AlertLayerHandler::UpdateAlerts() | |||
|             logger_->warn("Alert update timer error: {}", e.message()); | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             try | ||||
|             { | ||||
|                UpdateAlerts(); | ||||
|             } | ||||
|             catch (const std::exception& ex) | ||||
|             { | ||||
|                logger_->error(ex.what()); | ||||
|             } | ||||
|          } | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1637,6 +1637,8 @@ void MapWidgetImpl::RadarProductManagerConnect() | |||
|                boost::asio::post( | ||||
|                   threadPool_, | ||||
|                   [=, this]() | ||||
|                   { | ||||
|                      try | ||||
|                      { | ||||
|                         if (group == common::RadarProductGroup::Level2) | ||||
|                         { | ||||
|  | @ -1648,6 +1650,11 @@ void MapWidgetImpl::RadarProductManagerConnect() | |||
|                            radarProductManager_->LoadLevel3Data( | ||||
|                               product, latestTime, request); | ||||
|                         } | ||||
|                      } | ||||
|                      catch (const std::exception& ex) | ||||
|                      { | ||||
|                         logger_->error(ex.what()); | ||||
|                      } | ||||
|                   }); | ||||
|             } | ||||
|          }, | ||||
|  | @ -1672,7 +1679,10 @@ void MapWidgetImpl::InitializeNewRadarProductView( | |||
|    boost::asio::post(threadPool_, | ||||
|                      [=, this]() | ||||
|                      { | ||||
|                         auto radarProductView = context_->radar_product_view(); | ||||
|                         try | ||||
|                         { | ||||
|                            auto radarProductView = | ||||
|                               context_->radar_product_view(); | ||||
| 
 | ||||
|                            std::string colorTableFile = | ||||
|                               settings::PaletteSettings::Instance() | ||||
|  | @ -1688,6 +1698,11 @@ void MapWidgetImpl::InitializeNewRadarProductView( | |||
|                            } | ||||
| 
 | ||||
|                            radarProductView->Initialize(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| 
 | ||||
|    if (map_ != nullptr) | ||||
|  |  | |||
|  | @ -45,6 +45,7 @@ public: | |||
|    ~Impl() { threadPool_.join(); } | ||||
| 
 | ||||
|    void ConnectSignals(); | ||||
|    void ReloadDataSync(); | ||||
| 
 | ||||
|    boost::asio::thread_pool threadPool_ {1}; | ||||
| 
 | ||||
|  | @ -170,72 +171,77 @@ void PlacefileLayer::Deinitialize() | |||
| 
 | ||||
| void PlacefileLayer::ReloadData() | ||||
| { | ||||
|    boost::asio::post( | ||||
|       p->threadPool_, | ||||
|    boost::asio::post(p->threadPool_, | ||||
|                      [this]() | ||||
|                      { | ||||
|          logger_->debug("ReloadData: {}", p->placefileName_); | ||||
|                         try | ||||
|                         { | ||||
|                            p->ReloadDataSync(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
|          std::unique_lock lock {p->dataMutex_}; | ||||
| void PlacefileLayer::Impl::ReloadDataSync() | ||||
| { | ||||
|    logger_->debug("ReloadData: {}", placefileName_); | ||||
| 
 | ||||
|    std::unique_lock lock {dataMutex_}; | ||||
| 
 | ||||
|    std::shared_ptr<manager::PlacefileManager> placefileManager = | ||||
|       manager::PlacefileManager::Instance(); | ||||
| 
 | ||||
|          auto placefile = placefileManager->placefile(p->placefileName_); | ||||
|    auto placefile = placefileManager->placefile(placefileName_); | ||||
|    if (placefile == nullptr) | ||||
|    { | ||||
|       return; | ||||
|    } | ||||
| 
 | ||||
|    // Start draw items
 | ||||
|          p->placefileIcons_->StartIcons(); | ||||
|          p->placefileImages_->StartImages(placefile->name()); | ||||
|          p->placefileLines_->StartLines(); | ||||
|          p->placefilePolygons_->StartPolygons(); | ||||
|          p->placefileTriangles_->StartTriangles(); | ||||
|          p->placefileText_->StartText(); | ||||
|    placefileIcons_->StartIcons(); | ||||
|    placefileImages_->StartImages(placefile->name()); | ||||
|    placefileLines_->StartLines(); | ||||
|    placefilePolygons_->StartPolygons(); | ||||
|    placefileTriangles_->StartTriangles(); | ||||
|    placefileText_->StartText(); | ||||
| 
 | ||||
|          p->placefileIcons_->SetIconFiles(placefile->icon_files(), | ||||
|                                           placefile->name()); | ||||
|          p->placefileText_->SetFonts( | ||||
|             placefileManager->placefile_fonts(p->placefileName_)); | ||||
|    placefileIcons_->SetIconFiles(placefile->icon_files(), placefile->name()); | ||||
|    placefileText_->SetFonts(placefileManager->placefile_fonts(placefileName_)); | ||||
| 
 | ||||
|    for (auto& drawItem : placefile->GetDrawItems()) | ||||
|    { | ||||
|       switch (drawItem->itemType_) | ||||
|       { | ||||
|       case gr::Placefile::ItemType::Text: | ||||
|                p->placefileText_->AddText( | ||||
|                   std::static_pointer_cast<gr::Placefile::TextDrawItem>( | ||||
|                      drawItem)); | ||||
|          placefileText_->AddText( | ||||
|             std::static_pointer_cast<gr::Placefile::TextDrawItem>(drawItem)); | ||||
|          break; | ||||
| 
 | ||||
|       case gr::Placefile::ItemType::Icon: | ||||
|                p->placefileIcons_->AddIcon( | ||||
|                   std::static_pointer_cast<gr::Placefile::IconDrawItem>( | ||||
|                      drawItem)); | ||||
|          placefileIcons_->AddIcon( | ||||
|             std::static_pointer_cast<gr::Placefile::IconDrawItem>(drawItem)); | ||||
|          break; | ||||
| 
 | ||||
|       case gr::Placefile::ItemType::Line: | ||||
|                p->placefileLines_->AddLine( | ||||
|                   std::static_pointer_cast<gr::Placefile::LineDrawItem>( | ||||
|                      drawItem)); | ||||
|          placefileLines_->AddLine( | ||||
|             std::static_pointer_cast<gr::Placefile::LineDrawItem>(drawItem)); | ||||
|          break; | ||||
| 
 | ||||
|       case gr::Placefile::ItemType::Polygon: | ||||
|                p->placefilePolygons_->AddPolygon( | ||||
|                   std::static_pointer_cast<gr::Placefile::PolygonDrawItem>( | ||||
|                      drawItem)); | ||||
|          placefilePolygons_->AddPolygon( | ||||
|             std::static_pointer_cast<gr::Placefile::PolygonDrawItem>(drawItem)); | ||||
|          break; | ||||
| 
 | ||||
|       case gr::Placefile::ItemType::Image: | ||||
|                p->placefileImages_->AddImage( | ||||
|                   std::static_pointer_cast<gr::Placefile::ImageDrawItem>( | ||||
|                      drawItem)); | ||||
|          placefileImages_->AddImage( | ||||
|             std::static_pointer_cast<gr::Placefile::ImageDrawItem>(drawItem)); | ||||
|          break; | ||||
| 
 | ||||
|       case gr::Placefile::ItemType::Triangles: | ||||
|                p->placefileTriangles_->AddTriangles( | ||||
|          placefileTriangles_->AddTriangles( | ||||
|             std::static_pointer_cast<gr::Placefile::TrianglesDrawItem>( | ||||
|                drawItem)); | ||||
|          break; | ||||
|  | @ -246,15 +252,14 @@ void PlacefileLayer::ReloadData() | |||
|    } | ||||
| 
 | ||||
|    // Finish draw items
 | ||||
|          p->placefileIcons_->FinishIcons(); | ||||
|          p->placefileImages_->FinishImages(); | ||||
|          p->placefileLines_->FinishLines(); | ||||
|          p->placefilePolygons_->FinishPolygons(); | ||||
|          p->placefileTriangles_->FinishTriangles(); | ||||
|          p->placefileText_->FinishText(); | ||||
|    placefileIcons_->FinishIcons(); | ||||
|    placefileImages_->FinishImages(); | ||||
|    placefileLines_->FinishLines(); | ||||
|    placefilePolygons_->FinishPolygons(); | ||||
|    placefileTriangles_->FinishTriangles(); | ||||
|    placefileText_->FinishText(); | ||||
| 
 | ||||
|          Q_EMIT DataReloaded(); | ||||
|       }); | ||||
|    Q_EMIT self_->DataReloaded(); | ||||
| } | ||||
| 
 | ||||
| } // namespace map
 | ||||
|  |  | |||
|  | @ -119,9 +119,16 @@ void AlertProxyModelImpl::UpdateAlerts() | |||
|             logger_->warn("Alert update timer error: {}", e.message()); | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             try | ||||
|             { | ||||
|                UpdateAlerts(); | ||||
|             } | ||||
|             catch (const std::exception& ex) | ||||
|             { | ||||
|                logger_->error(ex.what()); | ||||
|             } | ||||
|          } | ||||
|       }); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -237,10 +237,19 @@ void OverlayProductView::Impl::LoadProduct( | |||
|    } | ||||
| 
 | ||||
|    // Load file
 | ||||
|    boost::asio::post( | ||||
|       threadPool_, | ||||
|    boost::asio::post(threadPool_, | ||||
|                      [=, this]() | ||||
|       { radarProductManager_->LoadLevel3Data(product, time, request); }); | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            radarProductManager_->LoadLevel3Data( | ||||
|                               product, time, request); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| void OverlayProductView::Impl::ResetProducts() | ||||
|  |  | |||
|  | @ -121,7 +121,18 @@ void RadarProductView::SelectTime(std::chrono::system_clock::time_point time) | |||
| 
 | ||||
| void RadarProductView::Update() | ||||
| { | ||||
|    boost::asio::post(thread_pool(), [this]() { ComputeSweep(); }); | ||||
|    boost::asio::post(thread_pool(), | ||||
|                      [this]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            ComputeSweep(); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|                         { | ||||
|                            logger_->error(ex.what()); | ||||
|                         } | ||||
|                      }); | ||||
| } | ||||
| 
 | ||||
| bool RadarProductView::IsInitialized() const | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat